]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Shell.java
Remove invalid SHA-256-Digests
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / widgets / Shell.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2016 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.events.*;
19 import org.eclipse.swt.graphics.*;
20 import org.eclipse.swt.internal.*;
21 import org.eclipse.swt.internal.win32.*;
22
23 /**
24  * Instances of this class represent the "windows"
25  * which the desktop or "window manager" is managing.
26  * Instances that do not have a parent (that is, they
27  * are built using the constructor, which takes a
28  * <code>Display</code> as the argument) are described
29  * as <em>top level</em> shells. Instances that do have
30  * a parent are described as <em>secondary</em> or
31  * <em>dialog</em> shells.
32  * <p>
33  * Instances are always displayed in one of the maximized,
34  * minimized or normal states:</p>
35  * <ul>
36  * <li>
37  * When an instance is marked as <em>maximized</em>, the
38  * window manager will typically resize it to fill the
39  * entire visible area of the display, and the instance
40  * is usually put in a state where it can not be resized
41  * (even if it has style <code>RESIZE</code>) until it is
42  * no longer maximized.
43  * </li><li>
44  * When an instance is in the <em>normal</em> state (neither
45  * maximized or minimized), its appearance is controlled by
46  * the style constants which were specified when it was created
47  * and the restrictions of the window manager (see below).
48  * </li><li>
49  * When an instance has been marked as <em>minimized</em>,
50  * its contents (client area) will usually not be visible,
51  * and depending on the window manager, it may be
52  * "iconified" (that is, replaced on the desktop by a small
53  * simplified representation of itself), relocated to a
54  * distinguished area of the screen, or hidden. Combinations
55  * of these changes are also possible.
56  * </li>
57  * </ul>
58  * <p>
59  * The <em>modality</em> of an instance may be specified using
60  * style bits. The modality style bits are used to determine
61  * whether input is blocked for other shells on the display.
62  * The <code>PRIMARY_MODAL</code> style allows an instance to block
63  * input to its parent. The <code>APPLICATION_MODAL</code> style
64  * allows an instance to block input to every other shell in the
65  * display. The <code>SYSTEM_MODAL</code> style allows an instance
66  * to block input to all shells, including shells belonging to
67  * different applications.
68  * </p><p>
69  * Note: The styles supported by this class are treated
70  * as <em>HINT</em>s, since the window manager for the
71  * desktop on which the instance is visible has ultimate
72  * control over the appearance and behavior of decorations
73  * and modality. For example, some window managers only
74  * support resizable windows and will always assume the
75  * RESIZE style, even if it is not set. In addition, if a
76  * modality style is not supported, it is "upgraded" to a
77  * more restrictive modality style that is supported. For
78  * example, if <code>PRIMARY_MODAL</code> is not supported,
79  * it would be upgraded to <code>APPLICATION_MODAL</code>.
80  * A modality style may also be "downgraded" to a less
81  * restrictive style. For example, most operating systems
82  * no longer support <code>SYSTEM_MODAL</code> because
83  * it can freeze up the desktop, so this is typically
84  * downgraded to <code>APPLICATION_MODAL</code>.</p>
85  * <dl>
86  * <dt><b>Styles:</b></dt>
87  * <dd>BORDER, CLOSE, MIN, MAX, NO_MOVE, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL, SHEET</dd>
88  * <dd>APPLICATION_MODAL, MODELESS, PRIMARY_MODAL, SYSTEM_MODAL</dd>
89  * <dt><b>Events:</b></dt>
90  * <dd>Activate, Close, Deactivate, Deiconify, Iconify</dd>
91  * </dl>
92  * <p>
93  * Class <code>SWT</code> provides two "convenience constants"
94  * for the most commonly required style combinations:</p>
95  * <dl>
96  * <dt><code>SHELL_TRIM</code></dt>
97  * <dd>
98  * the result of combining the constants which are required
99  * to produce a typical application top level shell: (that
100  * is, <code>CLOSE | TITLE | MIN | MAX | RESIZE</code>)
101  * </dd>
102  * <dt><code>DIALOG_TRIM</code></dt>
103  * <dd>
104  * the result of combining the constants which are required
105  * to produce a typical application dialog shell: (that
106  * is, <code>TITLE | CLOSE | BORDER</code>)
107  * </dd>
108  * </dl>
109  * <p>
110  * Note: Only one of the styles APPLICATION_MODAL, MODELESS,
111  * PRIMARY_MODAL and SYSTEM_MODAL may be specified.
112  * </p><p>
113  * IMPORTANT: This class is <em>not</em> intended to be subclassed.
114  * </p>
115  *
116  * @see Decorations
117  * @see SWT
118  * @see <a href="http://www.eclipse.org/swt/snippets/#shell">Shell snippets</a>
119  * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
120  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
121  * @noextend This class is not intended to be subclassed by clients.
122  */
123 public class Shell extends Decorations {
124         Menu activeMenu;
125         ToolTip [] toolTips;
126         long hIMC, hwndMDIClient, lpstrTip, toolTipHandle, balloonTipHandle, menuItemToolTipHandle;
127         int minWidth = SWT.DEFAULT, minHeight = SWT.DEFAULT;
128         long [] brushes;
129         boolean showWithParent, fullScreen, wasMaximized, modified, center;
130         String toolTitle, balloonTitle;
131         long toolIcon, balloonIcon;
132         long windowProc;
133         Control lastActive;
134         static /*final*/ long ToolTipProc;
135         static final long DialogProc;
136         static final TCHAR DialogClass = new TCHAR (0, "#32770", true);
137         final static int [] SYSTEM_COLORS = {
138                 OS.COLOR_BTNFACE,
139                 OS.COLOR_WINDOW,
140                 OS.COLOR_BTNTEXT,
141                 OS.COLOR_WINDOWTEXT,
142                 OS.COLOR_HIGHLIGHT,
143                 OS.COLOR_SCROLLBAR,
144         };
145         final static int BRUSHES_SIZE = 32;
146         static {
147                 WNDCLASS lpWndClass = new WNDCLASS ();
148                 OS.GetClassInfo (0, DialogClass, lpWndClass);
149                 DialogProc = lpWndClass.lpfnWndProc;
150         }
151
152 /**
153  * Constructs a new instance of this class. This is equivalent
154  * to calling <code>Shell((Display) null)</code>.
155  *
156  * @exception SWTException <ul>
157  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
158  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
159  * </ul>
160  */
161 public Shell () {
162         this ((Display) null);
163 }
164
165 /**
166  * Constructs a new instance of this class given only the style
167  * value describing its behavior and appearance. This is equivalent
168  * to calling <code>Shell((Display) null, style)</code>.
169  * <p>
170  * The style value is either one of the style constants defined in
171  * class <code>SWT</code> which is applicable to instances of this
172  * class, or must be built by <em>bitwise OR</em>'ing together
173  * (that is, using the <code>int</code> "|" operator) two or more
174  * of those <code>SWT</code> style constants. The class description
175  * lists the style constants that are applicable to the class.
176  * Style bits are also inherited from superclasses.
177  * </p>
178  *
179  * @param style the style of control to construct
180  *
181  * @exception SWTException <ul>
182  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
183  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
184  * </ul>
185  *
186  * @see SWT#BORDER
187  * @see SWT#CLOSE
188  * @see SWT#MIN
189  * @see SWT#MAX
190  * @see SWT#RESIZE
191  * @see SWT#TITLE
192  * @see SWT#TOOL
193  * @see SWT#NO_TRIM
194  * @see SWT#NO_MOVE
195  * @see SWT#SHELL_TRIM
196  * @see SWT#DIALOG_TRIM
197  * @see SWT#ON_TOP
198  * @see SWT#MODELESS
199  * @see SWT#PRIMARY_MODAL
200  * @see SWT#APPLICATION_MODAL
201  * @see SWT#SYSTEM_MODAL
202  * @see SWT#SHEET
203  */
204 public Shell (int style) {
205         this ((Display) null, style);
206 }
207
208 /**
209  * Constructs a new instance of this class given only the display
210  * to create it on. It is created with style <code>SWT.SHELL_TRIM</code>.
211  * <p>
212  * Note: Currently, null can be passed in for the display argument.
213  * This has the effect of creating the shell on the currently active
214  * display if there is one. If there is no current display, the
215  * shell is created on a "default" display. <b>Passing in null as
216  * the display argument is not considered to be good coding style,
217  * and may not be supported in a future release of SWT.</b>
218  * </p>
219  *
220  * @param display the display to create the shell on
221  *
222  * @exception SWTException <ul>
223  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
224  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
225  * </ul>
226  */
227 public Shell (Display display) {
228         this (display, SWT.SHELL_TRIM);
229 }
230
231 /**
232  * Constructs a new instance of this class given the display
233  * to create it on and a style value describing its behavior
234  * and appearance.
235  * <p>
236  * The style value is either one of the style constants defined in
237  * class <code>SWT</code> which is applicable to instances of this
238  * class, or must be built by <em>bitwise OR</em>'ing together
239  * (that is, using the <code>int</code> "|" operator) two or more
240  * of those <code>SWT</code> style constants. The class description
241  * lists the style constants that are applicable to the class.
242  * Style bits are also inherited from superclasses.
243  * </p><p>
244  * Note: Currently, null can be passed in for the display argument.
245  * This has the effect of creating the shell on the currently active
246  * display if there is one. If there is no current display, the
247  * shell is created on a "default" display. <b>Passing in null as
248  * the display argument is not considered to be good coding style,
249  * and may not be supported in a future release of SWT.</b>
250  * </p>
251  *
252  * @param display the display to create the shell on
253  * @param style the style of control to construct
254  *
255  * @exception SWTException <ul>
256  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
257  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
258  * </ul>
259  *
260  * @see SWT#BORDER
261  * @see SWT#CLOSE
262  * @see SWT#MIN
263  * @see SWT#MAX
264  * @see SWT#RESIZE
265  * @see SWT#TITLE
266  * @see SWT#TOOL
267  * @see SWT#NO_TRIM
268  * @see SWT#NO_MOVE
269  * @see SWT#SHELL_TRIM
270  * @see SWT#DIALOG_TRIM
271  * @see SWT#ON_TOP
272  * @see SWT#MODELESS
273  * @see SWT#PRIMARY_MODAL
274  * @see SWT#APPLICATION_MODAL
275  * @see SWT#SYSTEM_MODAL
276  * @see SWT#SHEET
277  */
278 public Shell (Display display, int style) {
279         this (display, null, style, 0, false);
280 }
281
282 Shell (Display display, Shell parent, int style, long handle, boolean embedded) {
283         super ();
284         checkSubclass ();
285         if (display == null) display = Display.getCurrent ();
286         if (display == null) display = Display.getDefault ();
287         if (!display.isValidThread ()) {
288                 error (SWT.ERROR_THREAD_INVALID_ACCESS);
289         }
290         if (parent != null && parent.isDisposed ()) {
291                 error (SWT.ERROR_INVALID_ARGUMENT);
292         }
293         this.center = parent != null && (style & SWT.SHEET) != 0;
294         this.style = checkStyle (parent, style);
295         this.parent = parent;
296         this.display = display;
297         this.handle = handle;
298         if (handle != 0 && !embedded) {
299                 state |= FOREIGN_HANDLE;
300         }
301         reskinWidget();
302         createWidget ();
303 }
304
305 /**
306  * Constructs a new instance of this class given only its
307  * parent. It is created with style <code>SWT.DIALOG_TRIM</code>.
308  * <p>
309  * Note: Currently, null can be passed in for the parent.
310  * This has the effect of creating the shell on the currently active
311  * display if there is one. If there is no current display, the
312  * shell is created on a "default" display. <b>Passing in null as
313  * the parent is not considered to be good coding style,
314  * and may not be supported in a future release of SWT.</b>
315  * </p>
316  *
317  * @param parent a shell which will be the parent of the new instance
318  *
319  * @exception IllegalArgumentException <ul>
320  *    <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
321  * </ul>
322  * @exception SWTException <ul>
323  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
324  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
325  * </ul>
326  */
327 public Shell (Shell parent) {
328         this (parent, SWT.DIALOG_TRIM);
329 }
330
331 /**
332  * Constructs a new instance of this class given its parent
333  * and a style value describing its behavior and appearance.
334  * <p>
335  * The style value is either one of the style constants defined in
336  * class <code>SWT</code> which is applicable to instances of this
337  * class, or must be built by <em>bitwise OR</em>'ing together
338  * (that is, using the <code>int</code> "|" operator) two or more
339  * of those <code>SWT</code> style constants. The class description
340  * lists the style constants that are applicable to the class.
341  * Style bits are also inherited from superclasses.
342  * </p><p>
343  * Note: Currently, null can be passed in for the parent.
344  * This has the effect of creating the shell on the currently active
345  * display if there is one. If there is no current display, the
346  * shell is created on a "default" display. <b>Passing in null as
347  * the parent is not considered to be good coding style,
348  * and may not be supported in a future release of SWT.</b>
349  * </p>
350  *
351  * @param parent a shell which will be the parent of the new instance
352  * @param style the style of control to construct
353  *
354  * @exception IllegalArgumentException <ul>
355  *    <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</li>
356  * </ul>
357  * @exception SWTException <ul>
358  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
359  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
360  * </ul>
361  *
362  * @see SWT#BORDER
363  * @see SWT#CLOSE
364  * @see SWT#MIN
365  * @see SWT#MAX
366  * @see SWT#RESIZE
367  * @see SWT#TITLE
368  * @see SWT#NO_TRIM
369  * @see SWT#NO_MOVE
370  * @see SWT#SHELL_TRIM
371  * @see SWT#DIALOG_TRIM
372  * @see SWT#ON_TOP
373  * @see SWT#TOOL
374  * @see SWT#MODELESS
375  * @see SWT#PRIMARY_MODAL
376  * @see SWT#APPLICATION_MODAL
377  * @see SWT#SYSTEM_MODAL
378  * @see SWT#SHEET
379  */
380 public Shell (Shell parent, int style) {
381         this (parent != null ? parent.display : null, parent, style, 0, false);
382 }
383
384 /**
385  * Invokes platform specific functionality to allocate a new shell
386  * that is embedded.
387  * <p>
388  * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
389  * API for <code>Shell</code>. It is marked public only so that it
390  * can be shared within the packages provided by SWT. It is not
391  * available on all platforms, and should never be called from
392  * application code.
393  * </p>
394  *
395  * @param display the display for the shell
396  * @param handle the handle for the shell
397  * @return a new shell object containing the specified display and handle
398  *
399  * @noreference This method is not intended to be referenced by clients.
400  */
401 public static Shell win32_new (Display display, long handle) {
402         return new Shell (display, null, SWT.NO_TRIM, handle, true);
403 }
404
405 /**
406  * Invokes platform specific functionality to allocate a new shell
407  * that is not embedded.
408  * <p>
409  * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
410  * API for <code>Shell</code>. It is marked public only so that it
411  * can be shared within the packages provided by SWT. It is not
412  * available on all platforms, and should never be called from
413  * application code.
414  * </p>
415  *
416  * @param display the display for the shell
417  * @param handle the handle for the shell
418  * @return a new shell object containing the specified display and handle
419  *
420  * @noreference This method is not intended to be referenced by clients.
421  *
422  * @since 3.3
423  */
424 public static Shell internal_new (Display display, long handle) {
425         return new Shell (display, null, SWT.NO_TRIM, handle, false);
426 }
427
428 static int checkStyle (Shell parent, int style) {
429         style = Decorations.checkStyle (style);
430         style &= ~SWT.TRANSPARENT;
431         int mask = SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.PRIMARY_MODAL;
432         if ((style & SWT.SHEET) != 0) {
433                 style &= ~SWT.SHEET;
434                 style |= parent == null ? SWT.SHELL_TRIM : SWT.DIALOG_TRIM;
435                 if ((style & mask) == 0) {
436                         style |= parent == null ? SWT.APPLICATION_MODAL : SWT.PRIMARY_MODAL;
437                 }
438         }
439         int bits = style & ~mask;
440         if ((style & SWT.SYSTEM_MODAL) != 0) return bits | SWT.SYSTEM_MODAL;
441         if ((style & SWT.APPLICATION_MODAL) != 0) return bits | SWT.APPLICATION_MODAL;
442         if ((style & SWT.PRIMARY_MODAL) != 0) return bits | SWT.PRIMARY_MODAL;
443         return bits;
444 }
445
446 /**
447  * Adds the listener to the collection of listeners who will
448  * be notified when operations are performed on the receiver,
449  * by sending the listener one of the messages defined in the
450  * <code>ShellListener</code> interface.
451  *
452  * @param listener the listener which should be notified
453  *
454  * @exception IllegalArgumentException <ul>
455  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
456  * </ul>
457  * @exception SWTException <ul>
458  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
459  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
460  * </ul>
461  *
462  * @see ShellListener
463  * @see #removeShellListener
464  */
465 public void addShellListener (ShellListener listener) {
466         checkWidget ();
467         if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
468         TypedListener typedListener = new TypedListener (listener);
469         addListener (SWT.Close,typedListener);
470         addListener (SWT.Iconify,typedListener);
471         addListener (SWT.Deiconify,typedListener);
472         addListener (SWT.Activate, typedListener);
473         addListener (SWT.Deactivate, typedListener);
474 }
475
476 long balloonTipHandle () {
477         if (balloonTipHandle == 0) createBalloonTipHandle ();
478         return balloonTipHandle;
479 }
480
481 @Override
482 long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
483         if (handle == 0) return 0;
484         if (hwnd == toolTipHandle || hwnd == balloonTipHandle || hwnd == menuItemToolTipHandle) {
485                 return OS.CallWindowProc (ToolTipProc, hwnd, msg, wParam, lParam);
486         }
487         if (hwndMDIClient != 0) {
488                 return OS.DefFrameProc (hwnd, hwndMDIClient, msg, wParam, lParam);
489         }
490         if (windowProc != 0) {
491                 return OS.CallWindowProc (windowProc, hwnd, msg, wParam, lParam);
492         }
493         if ((style & SWT.TOOL) != 0) {
494                 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
495                 if ((style & trim) == 0) return OS.DefWindowProc (hwnd, msg, wParam, lParam);
496         }
497         if ((style & SWT.NO_MOVE) != 0) {
498                 setItemEnabled (OS.SC_MOVE, false);
499         }
500         if (parent != null) {
501                 switch (msg) {
502                         case OS.WM_KILLFOCUS:
503                         case OS.WM_SETFOCUS:
504                                 return OS.DefWindowProc (hwnd, msg, wParam, lParam);
505                 }
506                 return OS.CallWindowProc (DialogProc, hwnd, msg, wParam, lParam);
507         }
508         return OS.DefWindowProc (hwnd, msg, wParam, lParam);
509 }
510
511 void center () {
512         if (parent == null) return;
513         Rectangle rect = getBoundsInPixels ();
514         Rectangle parentRect = display.mapInPixels (parent, null, parent.getClientAreaInPixels());
515         int x = Math.max (parentRect.x, parentRect.x + (parentRect.width - rect.width) / 2);
516         int y = Math.max (parentRect.y, parentRect.y + (parentRect.height - rect.height) / 2);
517         Rectangle monitorRect = parent.getMonitor ().getClientArea();
518         if (x + rect.width > monitorRect.x + monitorRect.width) {
519                 x = Math.max (monitorRect.x, monitorRect.x + monitorRect.width - rect.width);
520         } else {
521                 x = Math.max (x, monitorRect.x);
522         }
523         if (y + rect.height > monitorRect.y + monitorRect.height) {
524                 y = Math.max (monitorRect.y, monitorRect.y + monitorRect.height - rect.height);
525         } else {
526                 y = Math.max (y, monitorRect.y);
527         }
528         setLocationInPixels (x, y);
529 }
530
531 /**
532  * Requests that the window manager close the receiver in
533  * the same way it would be closed when the user clicks on
534  * the "close box" or performs some other platform specific
535  * key or mouse combination that indicates the window
536  * should be removed.
537  *
538  * @exception SWTException <ul>
539  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
540  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
541  * </ul>
542  *
543  * @see SWT#Close
544  * @see #dispose
545  */
546 public void close () {
547         checkWidget ();
548         closeWidget ();
549 }
550
551 void createBalloonTipHandle () {
552         balloonTipHandle = OS.CreateWindowEx (
553                 0,
554                 new TCHAR (0, OS.TOOLTIPS_CLASS, true),
555                 null,
556                 OS.TTS_ALWAYSTIP | OS.TTS_NOPREFIX | OS.TTS_BALLOON,
557                 OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
558                 handle,
559                 0,
560                 OS.GetModuleHandle (null),
561                 null);
562         if (balloonTipHandle == 0) error (SWT.ERROR_NO_HANDLES);
563         if (ToolTipProc == 0) {
564                 ToolTipProc = OS.GetWindowLongPtr (balloonTipHandle, OS.GWLP_WNDPROC);
565         }
566         /*
567         * Feature in Windows.  Despite the fact that the
568         * tool tip text contains \r\n, the tooltip will
569         * not honour the new line unless TTM_SETMAXTIPWIDTH
570         * is set.  The fix is to set TTM_SETMAXTIPWIDTH to
571         * a large value.
572         */
573         OS.SendMessage (balloonTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
574         display.addControl (balloonTipHandle, this);
575         OS.SetWindowLongPtr (balloonTipHandle, OS.GWLP_WNDPROC, display.windowProc);
576 }
577
578 @Override
579 void createHandle () {
580         boolean embedded = handle != 0 && (state & FOREIGN_HANDLE) == 0;
581
582         /*
583         * On Windows 98 and NT, setting a window to be the
584         * top most window using HWND_TOPMOST can result in a
585         * parent dialog shell being moved behind its parent
586         * if the dialog has a sibling that is currently on top
587         * This only occurs using SetWindowPos (), not when the
588         * handle is created.
589         */
590         /*
591         * The following code is intentionally commented.
592         */
593 //      if ((style & SWT.ON_TOP) != 0) display.lockActiveWindow = true;
594         if (handle == 0 || embedded) {
595                 super.createHandle ();
596         } else {
597                 state |= CANVAS;
598                 if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) == 0) {
599                         state |= THEME_BACKGROUND;
600                 }
601                 windowProc = OS.GetWindowLongPtr (handle, OS.GWL_WNDPROC);
602         }
603
604         /*
605         * The following code is intentionally commented.
606         */
607 //      if ((style & SWT.ON_TOP) != 0)  display.lockActiveWindow = false;
608
609         if (!embedded) {
610                 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
611                 bits &= ~(OS.WS_OVERLAPPED | OS.WS_CAPTION);
612                 bits |= OS.WS_POPUP;
613                 if ((style & SWT.TITLE) != 0) bits |= OS.WS_CAPTION;
614                 if ((style & SWT.NO_TRIM) == 0) {
615                         if ((style & (SWT.BORDER | SWT.RESIZE)) == 0) bits |= OS.WS_BORDER;
616                 }
617                 /*
618                 * Bug in Windows.  When the WS_CAPTION bits are cleared using
619                 * SetWindowLong(), Windows does not resize the client area of
620                 * the window to get rid of the caption until the first resize.
621                 * The fix is to use SetWindowPos() with SWP_DRAWFRAME to force
622                 * the frame to be redrawn and resized.
623                 */
624                 OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
625                 int flags = OS.SWP_DRAWFRAME | OS.SWP_NOMOVE | OS.SWP_NOSIZE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE;
626                 OS.SetWindowPos (handle, 0, 0, 0, 0, 0, flags);
627         }
628         if (OS.IsDBLocale) {
629                 hIMC = OS.ImmCreateContext ();
630                 if (hIMC != 0) OS.ImmAssociateContext (handle, hIMC);
631         }
632 }
633
634 void createMenuItemToolTipHandle() {
635         menuItemToolTipHandle = createToolTipHandle (0);
636 }
637
638 void createToolTip (ToolTip toolTip) {
639         int id = 0;
640         if (toolTips == null) toolTips = new ToolTip [4];
641         while (id < toolTips.length && toolTips [id] != null) id++;
642         if (id == toolTips.length) {
643                 ToolTip [] newToolTips = new ToolTip [toolTips.length + 4];
644                 System.arraycopy (toolTips, 0, newToolTips, 0, toolTips.length);
645                 toolTips = newToolTips;
646         }
647         toolTips [id] = toolTip;
648         toolTip.id = id + Display.ID_START;
649         TOOLINFO lpti = new TOOLINFO ();
650         lpti.cbSize = TOOLINFO.sizeof;
651         lpti.hwnd = handle;
652         lpti.uId = toolTip.id;
653         lpti.uFlags = OS.TTF_TRACK;
654         lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
655         OS.SendMessage (toolTip.hwndToolTip (), OS.TTM_ADDTOOL, 0, lpti);
656 }
657
658 void createToolTipHandle () {
659         toolTipHandle = createToolTipHandle (handle);
660 }
661
662 long createToolTipHandle (long parent) {
663         long toolTipHandle = OS.CreateWindowEx (
664                 0,
665                 new TCHAR (0, OS.TOOLTIPS_CLASS, true),
666                 null,
667                 OS.TTS_ALWAYSTIP | OS.TTS_NOPREFIX,
668                 OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
669                 parent,
670                 0,
671                 OS.GetModuleHandle (null),
672                 null);
673         if (toolTipHandle == 0) error (SWT.ERROR_NO_HANDLES);
674         if (ToolTipProc == 0) {
675                 ToolTipProc = OS.GetWindowLongPtr (toolTipHandle, OS.GWLP_WNDPROC);
676         }
677         /*
678         * Feature in Windows.  Despite the fact that the
679         * tool tip text contains \r\n, the tooltip will
680         * not honour the new line unless TTM_SETMAXTIPWIDTH
681         * is set.  The fix is to set TTM_SETMAXTIPWIDTH to
682         * a large value.
683         */
684         OS.SendMessage (toolTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
685         display.addControl (toolTipHandle, this);
686         OS.SetWindowLongPtr (toolTipHandle, OS.GWLP_WNDPROC, display.windowProc);
687         return toolTipHandle;
688 }
689
690 @Override
691 void deregister () {
692         super.deregister ();
693         if (toolTipHandle != 0) display.removeControl (toolTipHandle);
694         if (balloonTipHandle != 0) display.removeControl (balloonTipHandle);
695         if (menuItemToolTipHandle != 0) display.removeControl (menuItemToolTipHandle);
696 }
697
698 void destroyToolTip (ToolTip toolTip) {
699         if (toolTips == null) return;
700         toolTips [toolTip.id - Display.ID_START] = null;
701         if (balloonTipHandle != 0) {
702                 TOOLINFO lpti = new TOOLINFO ();
703                 lpti.cbSize = TOOLINFO.sizeof;
704                 lpti.uId = toolTip.id;
705                 lpti.hwnd = handle;
706                 OS.SendMessage (balloonTipHandle, OS.TTM_DELTOOL, 0, lpti);
707         }
708         toolTip.id = -1;
709 }
710
711 @Override
712 void destroyWidget () {
713         fixActiveShell ();
714         super.destroyWidget ();
715
716         /*
717         * Destroy context only after the controls that used it were destroyed.
718         * Technically, that shouldn't be necessary, because 'Control.releaseWidget'
719         * clears up association by calling 'OS.ImmAssociateContext (handle, 0)'.
720         * However, there's a bug in Windows 10 (see bug 526758), and this is the workaround.
721         */
722         if (OS.IsDBLocale) {
723                 if (hIMC != 0) OS.ImmDestroyContext (hIMC);
724         }
725 }
726
727 @Override
728 public void dispose () {
729         /*
730         * This code is intentionally commented.  On some
731         * platforms, the owner window is repainted right
732         * away when a dialog window exits.  This behavior
733         * is currently unspecified.
734         */
735 //      /*
736 //      * Note:  It is valid to attempt to dispose a widget
737 //      * more than once.  If this happens, fail silently.
738 //      */
739 //      if (!isValidWidget ()) return;
740 //      if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
741 //      Display oldDisplay = display;
742         super.dispose ();
743         // widget is disposed at this point
744 //      if (oldDisplay != null) oldDisplay.update ();
745 }
746
747 @Override
748 void enableWidget (boolean enabled) {
749         if (enabled) {
750                 state &= ~DISABLED;
751         } else {
752                 state |= DISABLED;
753         }
754         if (Display.TrimEnabled) {
755                 if (isActive ()) setItemEnabled (OS.SC_CLOSE, enabled);
756         } else {
757                 OS.EnableWindow (handle, enabled);
758         }
759 }
760
761 @Override
762 long findBrush (long value, int lbStyle) {
763         if (lbStyle == OS.BS_SOLID) {
764                 for (int i=0; i<SYSTEM_COLORS.length; i++) {
765                         if (value == OS.GetSysColor (SYSTEM_COLORS [i])) {
766                                 return OS.GetSysColorBrush (SYSTEM_COLORS [i]);
767                         }
768                 }
769         }
770         if (brushes == null) brushes = new long [BRUSHES_SIZE];
771         LOGBRUSH logBrush = new LOGBRUSH ();
772         for (int i=0; i<brushes.length; i++) {
773                 long hBrush = brushes [i];
774                 if (hBrush == 0) break;
775                 OS.GetObject (hBrush, LOGBRUSH.sizeof, logBrush);
776                 switch (logBrush.lbStyle) {
777                         case OS.BS_SOLID:
778                                 if (lbStyle == OS.BS_SOLID) {
779                                         if (logBrush.lbColor == value) return hBrush;
780                                 }
781                                 break;
782                         case OS.BS_PATTERN:
783                                 if (lbStyle == OS.BS_PATTERN) {
784                                         if (logBrush.lbHatch == value) return hBrush;
785                                 }
786                                 break;
787                 }
788         }
789         int length = brushes.length;
790         long hBrush = brushes [--length];
791         if (hBrush != 0) OS.DeleteObject (hBrush);
792         System.arraycopy (brushes, 0, brushes, 1, length);
793         switch (lbStyle) {
794                 case OS.BS_SOLID:
795                         hBrush = OS.CreateSolidBrush ((int)value);
796                         break;
797                 case OS.BS_PATTERN:
798                         hBrush = OS.CreatePatternBrush (value);
799                         break;
800         }
801         return brushes [0] = hBrush;
802 }
803
804 @Override
805 Control findBackgroundControl () {
806         return background != -1 || backgroundImage != null ? this : null;
807 }
808
809 @Override
810 Cursor findCursor () {
811         return cursor;
812 }
813
814 @Override
815 Control findThemeControl () {
816         return null;
817 }
818
819 ToolTip findToolTip (int id) {
820         if (toolTips == null) return null;
821         id = id - Display.ID_START;
822         return 0 <= id && id < toolTips.length ? toolTips [id] : null;
823 }
824
825 void fixActiveShell () {
826         /*
827         * Feature in Windows.  When the active shell is disposed
828         * or hidden, Windows normally makes the parent shell active
829         * and assigns focus.  This does not happen when the parent
830         * shell is disabled.  Instead, Windows assigns focus to the
831         * next shell on the desktop (possibly a shell in another
832         * application).  The fix is to activate the disabled parent
833         * shell before disposing or hiding the active shell.
834         */
835         long hwndParent = OS.GetParent (handle);
836         if (hwndParent != 0 && handle == OS.GetActiveWindow ()) {
837                 if (!OS.IsWindowEnabled (hwndParent) && OS.IsWindowVisible (hwndParent)) {
838                         OS.SetActiveWindow (hwndParent);
839                 }
840         }
841 }
842
843 void fixShell (Shell newShell, Control control) {
844         if (this == newShell) return;
845         if (control == lastActive) setActiveControl (null);
846         String toolTipText = control.toolTipText;
847         if (toolTipText != null) {
848                 control.setToolTipText (this, null);
849                 control.setToolTipText (newShell, toolTipText);
850         }
851 }
852
853 void fixToolTip () {
854         /*
855         * Bug in Windows.  On XP, when a tooltip is
856         * hidden due to a time out or mouse press,
857         * the tooltip remains active although no
858         * longer visible and won't show again until
859         * another tooltip becomes active.  If there
860         * is only one tooltip in the window,  it will
861         * never show again.  The fix is to remove the
862         * current tooltip and add it again every time
863         * the mouse leaves the control.
864         */
865         if (toolTipHandle == 0) return;
866         TOOLINFO lpti = new TOOLINFO ();
867         lpti.cbSize = TOOLINFO.sizeof;
868         if (OS.SendMessage (toolTipHandle, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
869                 if ((lpti.uFlags & OS.TTF_IDISHWND) != 0) {
870                         OS.SendMessage (toolTipHandle, OS.TTM_DELTOOL, 0, lpti);
871                         OS.SendMessage (toolTipHandle, OS.TTM_ADDTOOL, 0, lpti);
872                 }
873         }
874         TOOLINFO lptiMt = new TOOLINFO ();
875         lptiMt.cbSize = TOOLINFO.sizeof;
876         if (OS.SendMessage (menuItemToolTipHandle, OS.TTM_GETCURRENTTOOL, 0, lptiMt) != 0) {
877                 if ((lptiMt.uFlags & OS.TTF_IDISHWND) != 0) {
878                         OS.SendMessage (menuItemToolTipHandle, OS.TTM_DELTOOL, 0, lptiMt);
879                         OS.SendMessage (menuItemToolTipHandle, OS.TTM_ADDTOOL, 0, lptiMt);
880                 }
881         }
882 }
883
884 /**
885  * If the receiver is visible, moves it to the top of the
886  * drawing order for the display on which it was created
887  * (so that all other shells on that display, which are not
888  * the receiver's children will be drawn behind it) and forces
889  * the window manager to make the shell active.
890  *
891  * @exception SWTException <ul>
892  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
893  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
894  * </ul>
895  *
896  * @since 2.0
897  * @see Control#moveAbove
898  * @see Control#setFocus
899  * @see Control#setVisible
900  * @see Display#getActiveShell
901  * @see Decorations#setDefaultButton(Button)
902  * @see Shell#open
903  * @see Shell#setActive
904  */
905 public void forceActive () {
906         checkWidget ();
907         if(!isVisible()) return;
908         OS.SetForegroundWindow (handle);
909 }
910
911 @Override
912 void forceResize () {
913         /* Do nothing */
914 }
915
916 /**
917  * Returns the receiver's alpha value. The alpha value
918  * is between 0 (transparent) and 255 (opaque).
919  *
920  * @return the alpha value
921  *
922  * @exception SWTException <ul>
923  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
924  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
925  * </ul>
926  *
927  * @since 3.4
928  */
929 public int getAlpha () {
930         checkWidget ();
931         byte [] pbAlpha = new byte [1];
932         if (OS.GetLayeredWindowAttributes (handle, null, pbAlpha, null)) {
933                 return pbAlpha [0] & 0xFF;
934         }
935         return 0xFF;
936 }
937
938 @Override Rectangle getBoundsInPixels () {
939         if (OS.IsIconic (handle)) return super.getBoundsInPixels ();
940         RECT rect = new RECT ();
941         OS.GetWindowRect (handle, rect);
942         int width = rect.right - rect.left;
943         int height = rect.bottom - rect.top;
944         return new Rectangle (rect.left, rect.top, width, height);
945 }
946
947 ToolTip getCurrentToolTip () {
948         if (toolTipHandle != 0) {
949                 ToolTip tip = getCurrentToolTip (toolTipHandle);
950                 if (tip != null) return tip;
951         }
952         if (balloonTipHandle != 0) {
953                 ToolTip tip = getCurrentToolTip (balloonTipHandle);
954                 if (tip != null) return tip;
955         }
956         if (menuItemToolTipHandle != 0) {
957                 ToolTip tip = getCurrentToolTip (menuItemToolTipHandle);
958                 if (tip != null) return tip;
959         }
960         return null;
961 }
962
963 ToolTip getCurrentToolTip (long hwndToolTip) {
964         if (hwndToolTip == 0) return null;
965         if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, 0) != 0) {
966                 TOOLINFO lpti = new TOOLINFO ();
967                 lpti.cbSize = TOOLINFO.sizeof;
968                 if (OS.SendMessage (hwndToolTip, OS.TTM_GETCURRENTTOOL, 0, lpti) != 0) {
969                         if ((lpti.uFlags & OS.TTF_IDISHWND) == 0) return findToolTip ((int)lpti.uId);
970                 }
971         }
972         return null;
973 }
974
975 @Override
976 public boolean getEnabled () {
977         checkWidget ();
978         return (state & DISABLED) == 0;
979 }
980
981 /**
982  * Returns <code>true</code> if the receiver is currently
983  * in fullscreen state, and false otherwise.
984  * <p>
985  *
986  * @return the fullscreen state
987  *
988  * @exception SWTException <ul>
989  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
990  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
991  * </ul>
992  *
993  * @since 3.4
994  */
995 public boolean getFullScreen () {
996         checkWidget();
997         return fullScreen;
998 }
999
1000 /**
1001  * Returns the receiver's input method editor mode. This
1002  * will be the result of bitwise OR'ing together one or
1003  * more of the following constants defined in class
1004  * <code>SWT</code>:
1005  * <code>NONE</code>, <code>ROMAN</code>, <code>DBCS</code>,
1006  * <code>PHONETIC</code>, <code>NATIVE</code>, <code>ALPHA</code>.
1007  *
1008  * @return the IME mode
1009  *
1010  * @exception SWTException <ul>
1011  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1012  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1013  * </ul>
1014  *
1015  * @see SWT
1016  */
1017 public int getImeInputMode () {
1018         checkWidget ();
1019         if (!OS.IsDBLocale) return 0;
1020         long hIMC = OS.ImmGetContext (handle);
1021         int [] lpfdwConversion = new int [1], lpfdwSentence = new int [1];
1022         boolean open = OS.ImmGetOpenStatus (hIMC);
1023         if (open) open = OS.ImmGetConversionStatus (hIMC, lpfdwConversion, lpfdwSentence);
1024         OS.ImmReleaseContext (handle, hIMC);
1025         if (!open) return SWT.NONE;
1026         int result = 0;
1027         if ((lpfdwConversion [0] & OS.IME_CMODE_ROMAN) != 0) result |= SWT.ROMAN;
1028         if ((lpfdwConversion [0] & OS.IME_CMODE_FULLSHAPE) != 0) result |= SWT.DBCS;
1029         if ((lpfdwConversion [0] & OS.IME_CMODE_KATAKANA) != 0) return result | SWT.PHONETIC;
1030         if ((lpfdwConversion [0] & OS.IME_CMODE_NATIVE) != 0) return result | SWT.NATIVE;
1031         return result | SWT.ALPHA;
1032 }
1033
1034 @Override Point getLocationInPixels () {
1035         if (OS.IsIconic (handle)) return super.getLocationInPixels ();
1036         RECT rect = new RECT ();
1037         OS.GetWindowRect (handle, rect);
1038         return new Point (rect.left, rect.top);
1039 }
1040
1041 @Override
1042 public boolean getMaximized () {
1043         checkWidget ();
1044         return !fullScreen && super.getMaximized ();
1045 }
1046
1047 /**
1048  * Returns a point describing the minimum receiver's size. The
1049  * x coordinate of the result is the minimum width of the receiver.
1050  * The y coordinate of the result is the minimum height of the
1051  * receiver.
1052  *
1053  * @return the receiver's size
1054  *
1055  * @exception SWTException <ul>
1056  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1057  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1058  * </ul>
1059  *
1060  * @since 3.1
1061  */
1062 public Point getMinimumSize () {
1063         checkWidget ();
1064         return DPIUtil.autoScaleDown(getMinimumSizeInPixels());
1065 }
1066
1067 Point getMinimumSizeInPixels () {
1068         int width = Math.max (0, minWidth);
1069         int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
1070         if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
1071                 width = Math.max (width, OS.GetSystemMetrics (OS.SM_CXMINTRACK));
1072         }
1073         int height = Math.max (0, minHeight);
1074         if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
1075                 if ((style & SWT.RESIZE) != 0) {
1076                         height = Math.max (height, OS.GetSystemMetrics (OS.SM_CYMINTRACK));
1077                 } else {
1078                         RECT rect = new RECT ();
1079                         int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
1080                         int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
1081                         OS.AdjustWindowRectEx (rect, bits1, false, bits2);
1082                         height = Math.max (height, rect.bottom - rect.top);
1083                 }
1084         }
1085         return new Point (width,  height);
1086 }
1087
1088 /**
1089  * Gets the receiver's modified state.
1090  *
1091  * @return <code>true</code> if the receiver is marked as modified, or <code>false</code> otherwise
1092  *
1093  * @exception SWTException <ul>
1094  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1095  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1096  * </ul>
1097  *
1098  * @since 3.5
1099  */
1100 public boolean getModified () {
1101         checkWidget ();
1102         return modified;
1103 }
1104
1105 /**
1106  * Returns the region that defines the shape of the shell,
1107  * or <code>null</code> if the shell has the default shape.
1108  *
1109  * @return the region that defines the shape of the shell, or <code>null</code>
1110  *
1111  * @exception SWTException <ul>
1112  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1113  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1114  * </ul>
1115  *
1116  * @since 3.0
1117  *
1118  */
1119 @Override
1120 public Region getRegion () {
1121         /* This method is needed for the @since 3.0 Javadoc */
1122         checkWidget ();
1123         return region;
1124 }
1125
1126 @Override
1127 public Shell getShell () {
1128         checkWidget ();
1129         return this;
1130 }
1131
1132 @Override Point getSizeInPixels () {
1133         if (OS.IsIconic (handle)) return super.getSizeInPixels ();
1134         RECT rect = new RECT ();
1135         OS.GetWindowRect (handle, rect);
1136         int width = rect.right - rect.left;
1137         int height = rect.bottom - rect.top;
1138         return new Point (width, height);
1139 }
1140
1141 /**
1142  * Returns an array containing all shells which are
1143  * descendants of the receiver.
1144  * <p>
1145  * @return the dialog shells
1146  *
1147  * @exception SWTException <ul>
1148  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1149  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1150  * </ul>
1151  */
1152 public Shell [] getShells () {
1153         checkWidget ();
1154         int count = 0;
1155         Shell [] shells = display.getShells ();
1156         for (int i=0; i<shells.length; i++) {
1157                 Control shell = shells [i];
1158                 do {
1159                         shell = shell.parent;
1160                 } while (shell != null && shell != this);
1161                 if (shell == this) count++;
1162         }
1163         int index = 0;
1164         Shell [] result = new Shell [count];
1165         for (int i=0; i<shells.length; i++) {
1166                 Control shell = shells [i];
1167                 do {
1168                         shell = shell.parent;
1169                 } while (shell != null && shell != this);
1170                 if (shell == this) {
1171                         result [index++] = shells [i];
1172                 }
1173         }
1174         return result;
1175 }
1176
1177 /**
1178  * Returns a ToolBar object representing the tool bar that can be shown in the receiver's
1179  * trim. This will return <code>null</code> if the platform does not support tool bars that
1180  * are not part of the content area of the shell, or if the Shell's style does not support
1181  * having a tool bar.
1182  * <p>
1183  *
1184  * @return a ToolBar object representing the Shell's tool bar, or <code>null</code>.
1185  *
1186  * @exception SWTException <ul>
1187  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1188  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1189  * </ul>
1190  *
1191  * @since 3.7
1192  */
1193 public ToolBar getToolBar() {
1194         checkWidget ();
1195         return null;
1196 }
1197
1198 @Override
1199 Composite findDeferredControl () {
1200         return layoutCount > 0 ? this : null;
1201 }
1202
1203 @Override
1204 public boolean isEnabled () {
1205         checkWidget ();
1206         return getEnabled ();
1207 }
1208
1209 @Override
1210 public boolean isVisible () {
1211         checkWidget ();
1212         return getVisible ();
1213 }
1214
1215 long hwndMDIClient () {
1216         if (hwndMDIClient == 0) {
1217                 int widgetStyle = OS.MDIS_ALLCHILDSTYLES | OS.WS_CHILD | OS.WS_CLIPCHILDREN | OS.WS_CLIPSIBLINGS;
1218                 hwndMDIClient = OS.CreateWindowEx (
1219                         0,
1220                         new TCHAR (0, "MDICLIENT", true),
1221                         null,
1222                         widgetStyle,
1223                         0, 0, 0, 0,
1224                         handle,
1225                         0,
1226                         OS.GetModuleHandle (null),
1227                         new CREATESTRUCT ());
1228 //              OS.ShowWindow (hwndMDIClient, OS.SW_SHOW);
1229         }
1230         return hwndMDIClient;
1231 }
1232
1233 long menuItemToolTipHandle () {
1234         if (menuItemToolTipHandle == 0) createMenuItemToolTipHandle ();
1235         return menuItemToolTipHandle;
1236 }
1237
1238 /**
1239  * Moves the receiver to the top of the drawing order for
1240  * the display on which it was created (so that all other
1241  * shells on that display, which are not the receiver's
1242  * children will be drawn behind it), marks it visible,
1243  * sets the focus and asks the window manager to make the
1244  * shell active.
1245  *
1246  * @exception SWTException <ul>
1247  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1248  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1249  * </ul>
1250  *
1251  * @see Control#moveAbove
1252  * @see Control#setFocus
1253  * @see Control#setVisible
1254  * @see Display#getActiveShell
1255  * @see Decorations#setDefaultButton(Button)
1256  * @see Shell#setActive
1257  * @see Shell#forceActive
1258  */
1259 public void open () {
1260         checkWidget ();
1261         STARTUPINFO lpStartUpInfo = Display.lpStartupInfo;
1262         if (lpStartUpInfo == null || (lpStartUpInfo.dwFlags & OS.STARTF_USESHOWWINDOW) == 0) {
1263                 bringToTop ();
1264                 if (isDisposed ()) return;
1265         }
1266         OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
1267         setVisible (true);
1268         if (isDisposed ()) return;
1269         /*
1270         * Bug in Windows XP.  Despite the fact that an icon has been
1271         * set for a window, the task bar displays the wrong icon the
1272         * first time the window is made visible with ShowWindow() after
1273         * a call to BringToTop(), when a long time elapses between the
1274         * ShowWindow() and the time the event queue is read.  The icon
1275         * in the window trimming is correct but the one in the task
1276         * bar does not get updated.  The fix is to call PeekMessage()
1277         * with the flag PM_NOREMOVE and PM_QS_SENDMESSAGE to respond
1278         * to a cross thread WM_GETICON.
1279         *
1280         * NOTE: This allows other cross thread messages to be delivered,
1281         * most notably WM_ACTIVATE.
1282         */
1283         MSG msg = new MSG ();
1284         int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_SENDMESSAGE;
1285         OS.PeekMessage (msg, 0, 0, 0, flags);
1286         /*
1287          * When no widget has been given focus, or another push button has focus,
1288          * give focus to the default button. This avoids overriding the default
1289          * button.
1290          */
1291         boolean restored = restoreFocus ();
1292         if (!restored) {
1293                 restored = traverseGroup (true);
1294         }
1295         if (restored) {
1296                 Control focusControl = display.getFocusControl ();
1297                 if (focusControl instanceof Button && (focusControl.style & SWT.PUSH) != 0) {
1298                         restored = false;
1299                 }
1300         }
1301         if (!restored) {
1302                 if (saveDefault != null && !saveDefault.isDisposed ()) {
1303                         saveDefault.setFocus ();
1304                 } else {
1305                         setFocus ();
1306                 }
1307         }
1308 }
1309
1310 @Override
1311 public boolean print (GC gc) {
1312         checkWidget ();
1313         if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
1314         if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
1315         return false;
1316 }
1317
1318 @Override
1319 void register () {
1320         super.register ();
1321         if (toolTipHandle != 0) display.addControl (toolTipHandle, this);
1322         if (balloonTipHandle != 0) display.addControl (balloonTipHandle, this);
1323         if (menuItemToolTipHandle != 0) display.addControl (menuItemToolTipHandle, this);
1324 }
1325
1326 void releaseBrushes () {
1327         if (brushes != null) {
1328                 for (int i=0; i<brushes.length; i++) {
1329                         if (brushes [i] != 0) OS.DeleteObject (brushes [i]);
1330                 }
1331         }
1332         brushes = null;
1333 }
1334
1335 @Override
1336 void releaseChildren (boolean destroy) {
1337         Shell [] shells = getShells ();
1338         for (int i=0; i<shells.length; i++) {
1339                 Shell shell = shells [i];
1340                 if (shell != null && !shell.isDisposed ()) {
1341                         shell.release (false);
1342                 }
1343         }
1344         if (toolTips != null) {
1345                 for (int i=0; i<toolTips.length; i++) {
1346                         ToolTip toolTip = toolTips [i];
1347                         if (toolTip != null && !toolTip.isDisposed ()) {
1348                                 toolTip.release (false);
1349                         }
1350                 }
1351         }
1352         toolTips = null;
1353         super.releaseChildren (destroy);
1354 }
1355
1356 @Override
1357 void releaseHandle () {
1358         super.releaseHandle ();
1359         hwndMDIClient = 0;
1360 }
1361
1362 @Override
1363 void releaseParent () {
1364         /* Do nothing */
1365 }
1366
1367 @Override
1368 void releaseWidget () {
1369         super.releaseWidget ();
1370         releaseBrushes ();
1371         activeMenu = null;
1372         display.clearModal (this);
1373         if (lpstrTip != 0) {
1374                 long hHeap = OS.GetProcessHeap ();
1375                 OS.HeapFree (hHeap, 0, lpstrTip);
1376         }
1377         lpstrTip = 0;
1378         toolTipHandle = balloonTipHandle = menuItemToolTipHandle = 0;
1379         lastActive = null;
1380         toolTitle = balloonTitle = null;
1381 }
1382
1383 @Override
1384 void removeMenu (Menu menu) {
1385         super.removeMenu (menu);
1386         if (menu == activeMenu) activeMenu = null;
1387 }
1388
1389 /**
1390  * Removes the listener from the collection of listeners who will
1391  * be notified when operations are performed on the receiver.
1392  *
1393  * @param listener the listener which should no longer be notified
1394  *
1395  * @exception IllegalArgumentException <ul>
1396  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1397  * </ul>
1398  * @exception SWTException <ul>
1399  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1400  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1401  * </ul>
1402  *
1403  * @see ShellListener
1404  * @see #addShellListener
1405  */
1406 public void removeShellListener (ShellListener listener) {
1407         checkWidget ();
1408         if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1409         if (eventTable == null) return;
1410         eventTable.unhook (SWT.Close, listener);
1411         eventTable.unhook (SWT.Iconify,listener);
1412         eventTable.unhook (SWT.Deiconify,listener);
1413         eventTable.unhook (SWT.Activate, listener);
1414         eventTable.unhook (SWT.Deactivate, listener);
1415 }
1416
1417 @Override
1418 public void requestLayout () {
1419         layout (null, SWT.DEFER);
1420 }
1421
1422 @Override
1423 void reskinChildren (int flags) {
1424         Shell [] shells = getShells ();
1425         for (int i=0; i<shells.length; i++) {
1426                 Shell shell = shells [i];
1427                 if (shell != null) shell.reskin (flags);
1428         }
1429         if (toolTips != null) {
1430                 for (int i=0; i<toolTips.length; i++) {
1431                         ToolTip toolTip = toolTips [i];
1432                         if (toolTip != null) toolTip.reskin (flags);
1433                 }
1434         }
1435         super.reskinChildren (flags);
1436 }
1437
1438 @Override
1439 boolean sendKeyEvent (int type, int msg, long wParam, long lParam, Event event) {
1440         if (!isEnabled () || !isActive ()) return false;
1441         return super.sendKeyEvent (type, msg, wParam, lParam, event);
1442 }
1443
1444 /**
1445  * If the receiver is visible, moves it to the top of the
1446  * drawing order for the display on which it was created
1447  * (so that all other shells on that display, which are not
1448  * the receiver's children will be drawn behind it) and asks
1449  * the window manager to make the shell active
1450  *
1451  * @exception SWTException <ul>
1452  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1453  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1454  * </ul>
1455  *
1456  * @since 2.0
1457  * @see Control#moveAbove
1458  * @see Control#setFocus
1459  * @see Control#setVisible
1460  * @see Display#getActiveShell
1461  * @see Decorations#setDefaultButton(Button)
1462  * @see Shell#open
1463  * @see Shell#setActive
1464  */
1465 public void setActive () {
1466         checkWidget ();
1467         if (!isVisible ()) return;
1468         bringToTop ();
1469         // widget could be disposed at this point
1470 }
1471
1472 void setActiveControl (Control control) {
1473         setActiveControl (control, SWT.None);
1474 }
1475
1476 void setActiveControl (Control control, int type) {
1477         if (control != null && control.isDisposed ()) control = null;
1478         if (lastActive != null && lastActive.isDisposed ()) lastActive = null;
1479         if (lastActive == control) return;
1480
1481         /*
1482         * Compute the list of controls to be activated and
1483         * deactivated by finding the first common parent
1484         * control.
1485         */
1486         Control [] activate = (control == null) ? new Control [0] : control.getPath ();
1487         Control [] deactivate = (lastActive == null) ? new Control [0] : lastActive.getPath ();
1488         lastActive = control;
1489         int index = 0, length = Math.min (activate.length, deactivate.length);
1490         while (index < length) {
1491                 if (activate [index] != deactivate [index]) break;
1492                 index++;
1493         }
1494
1495         /*
1496         * It is possible (but unlikely), that application
1497         * code could have destroyed some of the widgets. If
1498         * this happens, keep processing those widgets that
1499         * are not disposed.
1500         */
1501         for (int i=deactivate.length-1; i>=index; --i) {
1502                 if (!deactivate [i].isDisposed ()) {
1503                         deactivate [i].sendEvent (SWT.Deactivate);
1504                 }
1505         }
1506         for (int i=activate.length-1; i>=index; --i) {
1507                 if (!activate [i].isDisposed ()) {
1508                         Event event = new Event ();
1509                         event.detail = type;
1510                         activate [i].sendEvent (SWT.Activate, event);
1511                 }
1512         }
1513 }
1514
1515 /**
1516  * Sets the receiver's alpha value which must be
1517  * between 0 (transparent) and 255 (opaque).
1518  * <p>
1519  * This operation requires the operating system's advanced
1520  * widgets subsystem which may not be available on some
1521  * platforms.
1522  * </p>
1523  * @param alpha the alpha value
1524  *
1525  * @exception SWTException <ul>
1526  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1527  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1528  * </ul>
1529  *
1530  * @since 3.4
1531  */
1532 public void setAlpha (int alpha) {
1533         checkWidget ();
1534         alpha &= 0xFF;
1535         int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
1536         if (alpha == 0xFF) {
1537                 OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits & ~OS.WS_EX_LAYERED);
1538                 int flags = OS.RDW_ERASE | OS.RDW_INVALIDATE | OS.RDW_FRAME | OS.RDW_ALLCHILDREN;
1539                 OS.RedrawWindow (handle, null, 0, flags);
1540         } else {
1541                 OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits | OS.WS_EX_LAYERED);
1542                 OS.SetLayeredWindowAttributes (handle, 0, (byte)alpha, OS.LWA_ALPHA);
1543         }
1544 }
1545
1546 @Override
1547 void setBoundsInPixels (int x, int y, int width, int height, int flags, boolean defer) {
1548         if (fullScreen) setFullScreen (false);
1549         /*
1550         * Bug in Windows.  When a window has alpha and
1551         * SetWindowPos() is called with SWP_DRAWFRAME,
1552         * the contents of the window are copied rather
1553         * than allowing the windows underneath to draw.
1554         * This causes pixel corruption.  The fix is to
1555         * clear the SWP_DRAWFRAME bits.
1556         */
1557         int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
1558         if ((bits & OS.WS_EX_LAYERED) != 0) {
1559                 flags &= ~OS.SWP_DRAWFRAME;
1560         }
1561         super.setBoundsInPixels (x, y, width, height, flags, false);
1562 }
1563
1564 @Override
1565 public void setEnabled (boolean enabled) {
1566         checkWidget ();
1567         if (((state & DISABLED) == 0) == enabled) return;
1568         super.setEnabled (enabled);
1569         if (enabled && handle == OS.GetActiveWindow ()) {
1570                 if (!restoreFocus ()) traverseGroup (true);
1571         }
1572 }
1573
1574 /**
1575  * Sets the full screen state of the receiver.
1576  * If the argument is <code>true</code> causes the receiver
1577  * to switch to the full screen state, and if the argument is
1578  * <code>false</code> and the receiver was previously switched
1579  * into full screen state, causes the receiver to switch back
1580  * to either the maximized or normal states.
1581  * <p>
1582  * Note: The result of intermixing calls to <code>setFullScreen(true)</code>,
1583  * <code>setMaximized(true)</code> and <code>setMinimized(true)</code> will
1584  * vary by platform. Typically, the behavior will match the platform user's
1585  * expectations, but not always. This should be avoided if possible.
1586  * </p>
1587  *
1588  * @param fullScreen the new fullscreen state
1589  *
1590  * @exception SWTException <ul>
1591  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1592  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1593  * </ul>
1594  *
1595  * @since 3.4
1596  */
1597 public void setFullScreen (boolean fullScreen) {
1598         checkWidget();
1599         if (this.fullScreen == fullScreen) return;
1600         int stateFlags = fullScreen ? OS.SW_SHOWMAXIMIZED : OS.SW_RESTORE;
1601         int styleFlags = OS.GetWindowLong (handle, OS.GWL_STYLE);
1602         int mask = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
1603         if ((style & mask) != 0) {
1604                 if (fullScreen) {
1605                         styleFlags &= ~(OS.WS_CAPTION | OS.WS_MAXIMIZEBOX | OS.WS_MINIMIZEBOX | OS.WS_THICKFRAME);
1606                 } else {
1607                         styleFlags |= OS.WS_CAPTION;
1608                         if ((style & SWT.MAX) != 0) styleFlags |= OS.WS_MAXIMIZEBOX;
1609                         if ((style & SWT.MIN) != 0) styleFlags |= OS.WS_MINIMIZEBOX;
1610                         if ((style & SWT.RESIZE) != 0) styleFlags |= OS.WS_THICKFRAME;
1611                 }
1612         }
1613         if (fullScreen) wasMaximized = getMaximized ();
1614         boolean visible = isVisible ();
1615         OS.SetWindowLong (handle, OS.GWL_STYLE, styleFlags);
1616         if (wasMaximized) {
1617                 OS.ShowWindow (handle, OS.SW_HIDE);
1618                 stateFlags = OS.SW_SHOWMAXIMIZED;
1619         }
1620         if (visible) OS.ShowWindow (handle, stateFlags);
1621         OS.UpdateWindow (handle);
1622         this.fullScreen = fullScreen;
1623 }
1624
1625 /**
1626  * Sets the input method editor mode to the argument which
1627  * should be the result of bitwise OR'ing together one or more
1628  * of the following constants defined in class <code>SWT</code>:
1629  * <code>NONE</code>, <code>ROMAN</code>, <code>DBCS</code>,
1630  * <code>PHONETIC</code>, <code>NATIVE</code>, <code>ALPHA</code>.
1631  *
1632  * @param mode the new IME mode
1633  *
1634  * @exception SWTException <ul>
1635  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1636  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1637  * </ul>
1638  *
1639  * @see SWT
1640  */
1641 public void setImeInputMode (int mode) {
1642         checkWidget ();
1643         if (!OS.IsDBLocale) return;
1644         boolean imeOn = mode != SWT.NONE;
1645         long hIMC = OS.ImmGetContext (handle);
1646         OS.ImmSetOpenStatus (hIMC, imeOn);
1647         if (imeOn) {
1648                 int [] lpfdwConversion = new int [1], lpfdwSentence = new int [1];
1649                 if (OS.ImmGetConversionStatus (hIMC, lpfdwConversion, lpfdwSentence)) {
1650                         int newBits = 0;
1651                         int oldBits = OS.IME_CMODE_NATIVE | OS.IME_CMODE_KATAKANA;
1652                         if ((mode & SWT.PHONETIC) != 0) {
1653                                 newBits = OS.IME_CMODE_KATAKANA | OS.IME_CMODE_NATIVE;
1654                                 oldBits = 0;
1655                         } else {
1656                                 if ((mode & SWT.NATIVE) != 0) {
1657                                         newBits = OS.IME_CMODE_NATIVE;
1658                                         oldBits = OS.IME_CMODE_KATAKANA;
1659                                 }
1660                         }
1661                         boolean fullShape = (mode & SWT.DBCS) != 0;
1662                         if ((mode & SWT.NATIVE) != 0) {
1663                                 long hkl = OS.GetKeyboardLayout (0);
1664                                 int langid = OS.PRIMARYLANGID (OS.LOWORD (hkl));
1665                                 if (langid == OS.LANG_JAPANESE) {
1666                                         fullShape = true;
1667                                 }
1668                         }
1669                         if (fullShape) {
1670                                 newBits |= OS.IME_CMODE_FULLSHAPE;
1671                         } else {
1672                                 oldBits |= OS.IME_CMODE_FULLSHAPE;
1673                         }
1674                         if ((mode & SWT.ROMAN) != 0) {
1675                                 newBits |= OS.IME_CMODE_ROMAN;
1676                         } else {
1677                                 oldBits |= OS.IME_CMODE_ROMAN;
1678                         }
1679                         lpfdwConversion [0] |= newBits;
1680                         lpfdwConversion [0] &= ~oldBits;
1681                         OS.ImmSetConversionStatus (hIMC, lpfdwConversion [0], lpfdwSentence [0]);
1682                 }
1683         }
1684         OS.ImmReleaseContext (handle, hIMC);
1685 }
1686
1687 /**
1688  * Sets the receiver's minimum size to the size specified by the arguments.
1689  * If the new minimum size is larger than the current size of the receiver,
1690  * the receiver is resized to the new minimum size.
1691  *
1692  * @param width the new minimum width for the receiver
1693  * @param height the new minimum height for the receiver
1694  *
1695  * @exception SWTException <ul>
1696  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1697  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1698  * </ul>
1699  *
1700  * @since 3.1
1701  */
1702 public void setMinimumSize (int width, int height) {
1703         checkWidget ();
1704         setMinimumSizeInPixels(DPIUtil.autoScaleUp(width), DPIUtil.autoScaleUp(height));
1705 }
1706
1707 void setMinimumSizeInPixels (int width, int height) {
1708         int widthLimit = 0, heightLimit = 0;
1709         int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
1710         if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
1711                 widthLimit = OS.GetSystemMetrics (OS.SM_CXMINTRACK);
1712                 if ((style & SWT.RESIZE) != 0) {
1713                         heightLimit = OS.GetSystemMetrics (OS.SM_CYMINTRACK);
1714                 } else {
1715                         RECT rect = new RECT ();
1716                         int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
1717                         int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
1718                         OS.AdjustWindowRectEx (rect, bits1, false, bits2);
1719                         heightLimit = rect.bottom - rect.top;
1720                 }
1721         }
1722         minWidth = Math.max (widthLimit, width);
1723         minHeight = Math.max (heightLimit, height);
1724         Point size = getSizeInPixels ();
1725         int newWidth = Math.max (size.x, minWidth);
1726         int newHeight = Math.max (size.y, minHeight);
1727         if (minWidth <= widthLimit) minWidth = SWT.DEFAULT;
1728         if (minHeight <= heightLimit) minHeight = SWT.DEFAULT;
1729         if (newWidth != size.x || newHeight != size.y) setSizeInPixels (newWidth, newHeight);
1730 }
1731
1732 /**
1733  * Sets the receiver's minimum size to the size specified by the argument.
1734  * If the new minimum size is larger than the current size of the receiver,
1735  * the receiver is resized to the new minimum size.
1736  *
1737  * @param size the new minimum size for the receiver
1738  *
1739  * @exception IllegalArgumentException <ul>
1740  *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
1741  * </ul>
1742  * @exception SWTException <ul>
1743  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1744  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1745  * </ul>
1746  *
1747  * @since 3.1
1748  */
1749 public void setMinimumSize (Point size) {
1750         checkWidget ();
1751         if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
1752         size = DPIUtil.autoScaleUp(size);
1753         setMinimumSizeInPixels(size.x, size.y);
1754 }
1755
1756 /**
1757  * Sets the receiver's modified state as specified by the argument.
1758  *
1759  * @param modified the new modified state for the receiver
1760  *
1761  * @exception SWTException <ul>
1762  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1763  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1764  * </ul>
1765  *
1766  * @since 3.5
1767  */
1768 public void setModified (boolean modified) {
1769         checkWidget ();
1770         this.modified = modified;
1771 }
1772
1773 void setItemEnabled (int cmd, boolean enabled) {
1774         long hMenu = OS.GetSystemMenu (handle, false);
1775         if (hMenu == 0) return;
1776         int flags = OS.MF_ENABLED;
1777         if (!enabled) flags = OS.MF_DISABLED | OS.MF_GRAYED;
1778         OS.EnableMenuItem (hMenu, cmd, OS.MF_BYCOMMAND | flags);
1779 }
1780
1781 @Override
1782 void setParent () {
1783         /* Do nothing.  Not necessary for Shells */
1784 }
1785
1786 /**
1787  * Sets the shape of the shell to the region specified
1788  * by the argument.  When the argument is null, the
1789  * default shape of the shell is restored.  The shell
1790  * must be created with the style SWT.NO_TRIM in order
1791  * to specify a region.
1792  * <p>
1793  * NOTE: This method also sets the size of the shell. Clients should
1794  * not call {@link #setSize} or {@link #setBounds} on this shell.
1795  * Furthermore, the passed region should not be modified any more.
1796  * </p>
1797  *
1798  * @param region the region that defines the shape of the shell (or null)
1799  *
1800  * @exception IllegalArgumentException <ul>
1801  *    <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</li>
1802  * </ul>
1803  * @exception SWTException <ul>
1804  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1805  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1806  * </ul>
1807  *
1808  * @since 3.0
1809  */
1810 @Override
1811 public void setRegion (Region region) {
1812         checkWidget ();
1813         if ((style & SWT.NO_TRIM) == 0) return;
1814         if (region != null) {
1815                 Rectangle bounds = region.getBounds ();
1816                 setSize (bounds.x + bounds.width, bounds.y + bounds.height);
1817         }
1818         super.setRegion (region);
1819 }
1820
1821 void setToolTipText (long hwnd, String text) {
1822         TOOLINFO lpti = new TOOLINFO ();
1823         lpti.cbSize = TOOLINFO.sizeof;
1824         lpti.hwnd = handle;
1825         lpti.uId = hwnd;
1826         long hwndToolTip = toolTipHandle ();
1827         if (text == null) {
1828                 OS.SendMessage (hwndToolTip, OS.TTM_DELTOOL, 0, lpti);
1829         } else {
1830                 if (OS.SendMessage (hwndToolTip, OS.TTM_GETTOOLINFO, 0, lpti) != 0) {
1831                         OS.SendMessage (hwndToolTip, OS.TTM_UPDATE, 0, 0);
1832                 } else {
1833                         lpti.uFlags = OS.TTF_IDISHWND | OS.TTF_SUBCLASS;
1834                         lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
1835                         OS.SendMessage (hwndToolTip, OS.TTM_ADDTOOL, 0, lpti);
1836                 }
1837         }
1838 }
1839
1840 void setToolTipText (NMTTDISPINFO lpnmtdi, char [] buffer) {
1841         /*
1842         * Ensure that the current position of the mouse
1843         * is inside the client area of the shell.  This
1844         * prevents tool tips from popping up over the
1845         * shell trimmings.
1846         */
1847         if (!hasCursor ()) return;
1848         long hHeap = OS.GetProcessHeap ();
1849         if (lpstrTip != 0) OS.HeapFree (hHeap, 0, lpstrTip);
1850         int byteCount = buffer.length * 2;
1851         lpstrTip = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
1852         OS.MoveMemory (lpstrTip, buffer, byteCount);
1853         lpnmtdi.lpszText = lpstrTip;
1854 }
1855
1856 void setToolTipTitle (long hwndToolTip, String text, int icon) {
1857         /*
1858         * Bug in Windows.  For some reason, when TTM_SETTITLE
1859         * is used to set the title of a tool tip, Windows leaks
1860         * GDI objects.  This happens even when TTM_SETTITLE is
1861         * called with TTI_NONE and NULL.  The documentation
1862         * states that Windows copies the icon and that the
1863         * programmer must free the copy but does not provide
1864         * API to get the icon.  For example, when TTM_SETTITLE
1865         * is called with ICON_ERROR, when TTM_GETTITLE is used
1866         * to query the title and the icon, the uTitleBitmap
1867         * field in the TTGETTITLE struct is zero.  The fix
1868         * is to remember these values, only set them when then
1869         * change and leak less.
1870         *
1871         * NOTE:  This only happens on Vista.
1872         */
1873         if (hwndToolTip != toolTipHandle && hwndToolTip != balloonTipHandle && hwndToolTip != menuItemToolTipHandle) {
1874                 return;
1875         }
1876         if (hwndToolTip == toolTipHandle || hwndToolTip == menuItemToolTipHandle) {
1877                 if (text == toolTitle || (toolTitle != null && toolTitle.equals (text))) {
1878                         if (icon == toolIcon) return;
1879                 }
1880                 toolTitle = text;
1881                 toolIcon = icon;
1882         } else {
1883                 if (hwndToolTip == balloonTipHandle) {
1884                         if (text == balloonTitle || (balloonTitle != null && balloonTitle.equals (text))) {
1885                                 if (icon == toolIcon) return;
1886                         }
1887                         balloonTitle = text;
1888                         balloonIcon = icon;
1889                 }
1890         }
1891         if (text != null) {
1892                 /*
1893                 * Feature in Windows. The text point to by pszTitle
1894                 * must not exceed 100 characters in length, including
1895                 * the null terminator.
1896                 */
1897                 if (text.length () > 99) text = text.substring (0, 99);
1898                 TCHAR pszTitle = new TCHAR (getCodePage (), text, true);
1899                 OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, icon, pszTitle);
1900         } else {
1901                 OS.SendMessage (hwndToolTip, OS.TTM_SETTITLE, 0, 0);
1902         }
1903 }
1904
1905 @Override
1906 public void setVisible (boolean visible) {
1907         checkWidget ();
1908         /*
1909         * Feature in Windows.  When ShowWindow() is called used to hide
1910         * a window, Windows attempts to give focus to the parent. If the
1911         * parent is disabled by EnableWindow(), focus is assigned to
1912         * another windows on the desktop.  This means that if you hide
1913         * a modal window before the parent is enabled, the parent will
1914         * not come to the front.  The fix is to change the modal state
1915         * before hiding or showing a window so that this does not occur.
1916         */
1917         int mask = SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
1918         if ((style & mask) != 0) {
1919                 if (visible) {
1920                         display.setModalShell (this);
1921                         if ((style & (SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL)) != 0) {
1922                                 display.setModalDialog (null);
1923                         }
1924                         Control control = display._getFocusControl ();
1925                         if (control != null && !control.isActive ()) {
1926                                 bringToTop ();
1927                                 if (isDisposed ()) return;
1928                         }
1929                         long hwndShell = OS.GetActiveWindow ();
1930                         if (hwndShell == 0) {
1931                                 if (parent != null) hwndShell = parent.handle;
1932                         }
1933                         if (hwndShell != 0) {
1934                                 OS.SendMessage (hwndShell, OS.WM_CANCELMODE, 0, 0);
1935                         }
1936                         OS.ReleaseCapture ();
1937                 } else {
1938                         display.clearModal (this);
1939                 }
1940         } else {
1941                 updateModal ();
1942         }
1943
1944         /*
1945         * Bug in Windows.  Calling ShowOwnedPopups() to hide the
1946         * child windows of a hidden window causes the application
1947         * to be deactivated.  The fix is to call ShowOwnedPopups()
1948         * to hide children before hiding the parent.
1949         */
1950         if (showWithParent && !visible) {
1951                 OS.ShowOwnedPopups (handle, false);
1952         }
1953         if (!visible) fixActiveShell ();
1954         if (visible && center && !moved) {
1955                 center ();
1956                 if (isDisposed ()) return;
1957         }
1958         super.setVisible (visible);
1959         if (isDisposed ()) return;
1960         if (showWithParent != visible) {
1961                 showWithParent = visible;
1962                 if (visible) {
1963                         OS.ShowOwnedPopups (handle, true);
1964                 }
1965         }
1966
1967         /* Make the foreign window parent appear in the task bar */
1968         if (visible) {
1969                 if (parent != null && (parent.state & FOREIGN_HANDLE) != 0) {
1970                         long hwndParent = parent.handle;
1971                         int style = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
1972                         if ((style & OS.WS_EX_TOOLWINDOW) != 0) {
1973                                 OS.SetWindowLong (hwndParent, OS.GWL_EXSTYLE, style & ~OS.WS_EX_TOOLWINDOW);
1974                                 /*
1975                                 * Bug in Windows.  The window does not show in the task bar when
1976                                 * WS_EX_TOOLWINDOW is removed after the window has already been shown.
1977                                 * The fix is to hide and shown the shell.
1978                                 */
1979                                 OS.ShowWindow (hwndParent, OS.SW_HIDE);
1980                                 OS.ShowWindow (hwndParent, OS.SW_RESTORE);
1981                         }
1982                 }
1983         }
1984 }
1985
1986 @Override
1987 void subclass () {
1988         super.subclass ();
1989         if (ToolTipProc != 0) {
1990                 long newProc = display.windowProc;
1991                 if (toolTipHandle != 0) {
1992                         OS.SetWindowLongPtr (toolTipHandle, OS.GWLP_WNDPROC, newProc);
1993                 }
1994                 if (balloonTipHandle != 0) {
1995                         OS.SetWindowLongPtr (balloonTipHandle, OS.GWLP_WNDPROC, newProc);
1996                 }
1997                 if (menuItemToolTipHandle != 0) {
1998                         OS.SetWindowLongPtr (menuItemToolTipHandle, OS.GWLP_WNDPROC, newProc);
1999                 }
2000         }
2001 }
2002
2003 long toolTipHandle () {
2004         if (toolTipHandle == 0) createToolTipHandle ();
2005         return toolTipHandle;
2006 }
2007
2008 @Override
2009 boolean translateAccelerator (MSG msg) {
2010         if (!isEnabled () || !isActive ()) return false;
2011         if (menuBar != null && !menuBar.isEnabled ()) return false;
2012         return translateMDIAccelerator (msg) || translateMenuAccelerator (msg);
2013 }
2014
2015 @Override
2016 boolean traverseEscape () {
2017         if (parent == null) return false;
2018         if (!isVisible () || !isEnabled ()) return false;
2019         close ();
2020         return true;
2021 }
2022
2023 @Override
2024 void unsubclass () {
2025         super.unsubclass ();
2026         if (ToolTipProc != 0) {
2027                 if (toolTipHandle != 0) {
2028                         OS.SetWindowLongPtr (toolTipHandle, OS.GWLP_WNDPROC, ToolTipProc);
2029                 }
2030                 if (toolTipHandle != 0) {
2031                         OS.SetWindowLongPtr (toolTipHandle, OS.GWLP_WNDPROC, ToolTipProc);
2032                 }
2033                 if (menuItemToolTipHandle != 0) {
2034                         OS.SetWindowLongPtr (menuItemToolTipHandle, OS.GWLP_WNDPROC, ToolTipProc);
2035                 }
2036         }
2037 }
2038
2039 void updateModal () {
2040         if (Display.TrimEnabled) {
2041                 setItemEnabled (OS.SC_CLOSE, isActive ());
2042         } else {
2043                 OS.EnableWindow (handle, isActive ());
2044         }
2045 }
2046
2047 @Override
2048 CREATESTRUCT widgetCreateStruct () {
2049         return null;
2050 }
2051
2052 @Override
2053 long widgetParent () {
2054         if (handle != 0) return handle;
2055         return parent != null ? parent.handle : 0;
2056 }
2057
2058 @Override
2059 int widgetExtStyle () {
2060         int bits = super.widgetExtStyle () & ~OS.WS_EX_MDICHILD;
2061         if ((style & SWT.TOOL) != 0) bits |= OS.WS_EX_TOOLWINDOW;
2062
2063         /*
2064         * Feature in Windows.  When a window that does not have a parent
2065         * is created, it is automatically added to the Windows Task Bar,
2066         * even when it has no title.  The fix is to use WS_EX_TOOLWINDOW
2067         * which does not cause the window to appear in the Task Bar.
2068         */
2069         if (parent == null) {
2070                 if ((style & SWT.ON_TOP) != 0) {
2071                         int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
2072                         if ((style & SWT.NO_TRIM) != 0 || (style & trim) == 0) {
2073                                 bits |= OS.WS_EX_TOOLWINDOW;
2074                         }
2075                 }
2076         }
2077
2078         if ((style & SWT.ON_TOP) != 0) bits |= OS.WS_EX_TOPMOST;
2079         return bits;
2080 }
2081
2082 @Override
2083 TCHAR windowClass () {
2084         if ((style & SWT.TOOL) != 0) {
2085                 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
2086                 if ((style & trim) == 0) return display.windowShadowClass;
2087         }
2088         return parent != null ? DialogClass : super.windowClass ();
2089 }
2090
2091 @Override
2092 long windowProc () {
2093         if (windowProc != 0) return windowProc;
2094         if ((style & SWT.TOOL) != 0) {
2095                 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.BORDER | SWT.RESIZE;
2096                 if ((style & trim) == 0) return super.windowProc ();
2097         }
2098         return parent != null ? DialogProc : super.windowProc ();
2099 }
2100
2101 @Override
2102 long windowProc (long hwnd, int msg, long wParam, long lParam) {
2103         if (handle == 0) return 0;
2104         if((style & SWT.NO_MOVE) != 0 && msg == OS.WM_NCLBUTTONDOWN && wParam == OS.HTCAPTION) return 0;
2105         if (hwnd == toolTipHandle || hwnd == balloonTipHandle || hwnd == menuItemToolTipHandle) {
2106                 switch (msg) {
2107                         case OS.WM_TIMER: {
2108                                 if (wParam != ToolTip.TIMER_ID) break;
2109                                 ToolTip tip = getCurrentToolTip (hwnd);
2110                                 if (tip != null && tip.autoHide) {
2111                                         tip.setVisible (false);
2112                                 }
2113                                 break;
2114                         }
2115                         case OS.WM_LBUTTONDOWN: {
2116                                 ToolTip tip = getCurrentToolTip (hwnd);
2117                                 if (tip != null) {
2118                                         tip.setVisible (false);
2119                                         tip.sendSelectionEvent (SWT.Selection);
2120                                 }
2121                                 break;
2122                         }
2123                 }
2124                 return callWindowProc (hwnd, msg, wParam, lParam);
2125         }
2126         if (hwnd == handle) {
2127                 if ((int)msg == Display.TASKBARBUTTONCREATED) {
2128                         if (display.taskBar != null) {
2129                                 for (TaskItem item : display.taskBar.items) {
2130                                         if (item != null && item.shell == this) {
2131                                                 item.recreate ();
2132                                                 break;
2133                                         }
2134                                 }
2135                         }
2136                 }
2137         }
2138         return super.windowProc (hwnd, msg, wParam, lParam);
2139 }
2140
2141 @Override
2142 int widgetStyle () {
2143         int bits = super.widgetStyle ();
2144         if (handle != 0) return bits | OS.WS_CHILD;
2145         bits &= ~OS.WS_CHILD;
2146
2147         /*
2148         * Use WS_OVERLAPPED for all windows, either dialog or top level
2149         * so that CreateWindowEx () will respect CW_USEDEFAULT and set
2150         * the default window location and size.
2151         *
2152         * NOTE:  When a WS_OVERLAPPED window is created, Windows gives
2153         * the new window WS_CAPTION style bits.  These two constants are
2154         * as follows:
2155         *
2156         *       WS_OVERLAPPED = 0
2157         *       WS_CAPTION = WS_BORDER | WS_DLGFRAME
2158         *
2159         */
2160         return bits | OS.WS_OVERLAPPED | OS.WS_CAPTION;
2161 }
2162
2163 @Override
2164 LRESULT WM_ACTIVATE (long wParam, long lParam) {
2165         /*
2166         * Bug in Windows XP.  When a Shell is deactivated, the
2167         * IME composition window does not go away. This causes
2168         * repaint issues.  The fix is to commit the composition
2169         * string.
2170         */
2171         if (OS.LOWORD (wParam) == 0 && OS.IsDBLocale && hIMC != 0) {
2172                 if (OS.ImmGetOpenStatus (hIMC)) {
2173                         OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0);
2174                 }
2175         }
2176
2177         /* Process WM_ACTIVATE */
2178         LRESULT result = super.WM_ACTIVATE (wParam, lParam);
2179         if (OS.LOWORD (wParam) == 0) {
2180                 if (lParam == 0 || (lParam != toolTipHandle && lParam != balloonTipHandle
2181                                 && lParam != menuItemToolTipHandle)) {
2182                         ToolTip tip = getCurrentToolTip ();
2183                         if (tip != null) tip.setVisible (false);
2184                 }
2185         }
2186         return parent != null ? LRESULT.ZERO : result;
2187 }
2188
2189 @Override
2190 LRESULT WM_DESTROY (long wParam, long lParam) {
2191         LRESULT result = super.WM_DESTROY (wParam, lParam);
2192         /*
2193         * When the shell is a WS_CHILD window of a non-SWT
2194         * window, the destroy code does not get called because
2195         * the non-SWT window does not call dispose ().  Instead,
2196         * the destroy code is called here in WM_DESTROY.
2197         */
2198         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
2199         if ((bits & OS.WS_CHILD) != 0) {
2200                 releaseParent ();
2201                 release (false);
2202         }
2203         return result;
2204 }
2205
2206 @Override
2207 LRESULT WM_ERASEBKGND (long wParam, long lParam) {
2208         LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
2209         if (result != null) return result;
2210         /*
2211         * Feature in Windows.  When a shell is resized by dragging
2212         * the resize handles, Windows temporarily fills in black
2213         * rectangles where the new contents of the shell should
2214         * draw.  The fix is to always draw the background of shells.
2215         *
2216         * NOTE: This only happens on Vista.
2217         */
2218         if (OS.WIN32_VERSION == OS.VERSION (6, 0)) {
2219                 drawBackground (wParam);
2220                 return LRESULT.ONE;
2221         }
2222         return result;
2223 }
2224
2225 @Override
2226 LRESULT WM_ENTERIDLE (long wParam, long lParam) {
2227         LRESULT result = super.WM_ENTERIDLE (wParam, lParam);
2228         if (result != null) return result;
2229         Display display = this.display;
2230         if (display.runAsyncMessages (false)) display.wakeThread ();
2231         return result;
2232 }
2233
2234 @Override
2235 LRESULT WM_GETMINMAXINFO (long wParam, long lParam) {
2236         LRESULT result = super.WM_GETMINMAXINFO (wParam, lParam);
2237         if (result != null) return result;
2238         if (minWidth != SWT.DEFAULT || minHeight != SWT.DEFAULT) {
2239                 MINMAXINFO info = new MINMAXINFO ();
2240                 OS.MoveMemory (info, lParam, MINMAXINFO.sizeof);
2241                 if (minWidth != SWT.DEFAULT) info.ptMinTrackSize_x = minWidth;
2242                 if (minHeight != SWT.DEFAULT) info.ptMinTrackSize_y = minHeight;
2243                 OS.MoveMemory (lParam, info, MINMAXINFO.sizeof);
2244                 return LRESULT.ZERO;
2245         }
2246         return result;
2247 }
2248
2249 @Override
2250 LRESULT WM_MOUSEACTIVATE (long wParam, long lParam) {
2251         LRESULT result = super.WM_MOUSEACTIVATE (wParam, lParam);
2252         if (result != null) return result;
2253
2254         /*
2255         * Check for WM_MOUSEACTIVATE when an MDI shell is active
2256         * and stop the normal shell activation but allow the mouse
2257         * down to be delivered.
2258         */
2259         int hittest = (short) OS.LOWORD (lParam);
2260         switch (hittest) {
2261                 case OS.HTERROR:
2262                 case OS.HTTRANSPARENT:
2263                 case OS.HTNOWHERE:
2264                         break;
2265                 default: {
2266                         Control control = display._getFocusControl ();
2267                         if (control != null) {
2268                                 Decorations decorations = control.menuShell ();
2269                                 if (decorations.getShell () == this && decorations != this) {
2270                                         display.ignoreRestoreFocus = true;
2271                                         display.lastHittest = hittest;
2272                                         display.lastHittestControl = null;
2273                                         if (hittest == OS.HTMENU || hittest == OS.HTSYSMENU) {
2274                                                 display.lastHittestControl = control;
2275                                                 return null;
2276                                         }
2277                                         return new LRESULT (OS.MA_NOACTIVATE);
2278                                 }
2279                         }
2280                 }
2281         }
2282         if (hittest == OS.HTMENU) return null;
2283
2284         /*
2285         * Get the current location of the cursor,
2286         * not the location of the cursor when the
2287         * WM_MOUSEACTIVATE was generated.  This is
2288         * strictly incorrect but is necessary in
2289         * order to support Activate and Deactivate
2290         * events for embedded widgets that have
2291         * their own event loop.  In that case, the
2292         * cursor location reported by GetMessagePos()
2293         * is the one for our event loop, not the
2294         * embedded widget's event loop.
2295         */
2296         POINT pt = new POINT ();
2297         if (!OS.GetCursorPos (pt)) {
2298                 int pos = OS.GetMessagePos ();
2299                 OS.POINTSTOPOINT (pt, pos);
2300         }
2301         long hwnd = OS.WindowFromPoint (pt);
2302         if (hwnd == 0) return null;
2303         Control control = display.findControl (hwnd);
2304
2305         /*
2306         * When a shell is created with SWT.ON_TOP and SWT.NO_FOCUS,
2307         * do not activate the shell when the user clicks on the
2308         * the client area or on the border or a control within the
2309         * shell that does not take focus.
2310         */
2311         if (control != null && (control.state & CANVAS) != 0) {
2312                 if ((control.style & SWT.NO_FOCUS) != 0) {
2313                         int bits = SWT.ON_TOP | SWT.NO_FOCUS;
2314                         if ((style & bits) == bits) {
2315                                 if (hittest == OS.HTBORDER || hittest == OS.HTCLIENT) {
2316                                         return new LRESULT (OS.MA_NOACTIVATE);
2317                                 }
2318                         }
2319                 }
2320         }
2321
2322         long code = callWindowProc (handle, OS.WM_MOUSEACTIVATE, wParam, lParam);
2323         setActiveControl (control, SWT.MouseDown);
2324         return new LRESULT (code);
2325 }
2326
2327 @Override
2328 LRESULT WM_MOVE (long wParam, long lParam) {
2329         LRESULT result = super.WM_MOVE (wParam, lParam);
2330         if (result != null) return result;
2331         ToolTip tip = getCurrentToolTip ();
2332         if (tip != null) tip.setVisible (false);
2333         return result;
2334 }
2335
2336 @Override
2337 LRESULT WM_NCHITTEST (long wParam, long lParam) {
2338         if (!OS.IsWindowEnabled (handle)) return null;
2339         if (!isEnabled () || !isActive ()) {
2340                 if (!Display.TrimEnabled) return new LRESULT (OS.HTNOWHERE);
2341                 long hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
2342                 if (hittest == OS.HTCLIENT || hittest == OS.HTMENU) hittest = OS.HTBORDER;
2343                 return new LRESULT (hittest);
2344         }
2345         if (menuBar != null && !menuBar.getEnabled ()) {
2346                 long hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
2347                 if (hittest == OS.HTMENU) hittest = OS.HTBORDER;
2348                 return new LRESULT (hittest);
2349         }
2350         return null;
2351 }
2352
2353 @Override
2354 LRESULT WM_NCLBUTTONDOWN (long wParam, long lParam) {
2355         LRESULT result = super.WM_NCLBUTTONDOWN (wParam, lParam);
2356         if (result != null) return result;
2357         /*
2358         * When the normal activation was interrupted in WM_MOUSEACTIVATE
2359         * because the active shell was an MDI shell, set the active window
2360         * to the top level shell but lock the active window and stop focus
2361         * changes.  This allows the user to interact the top level shell
2362         * in the normal manner.
2363         */
2364         if (!display.ignoreRestoreFocus) return result;
2365         Display display = this.display;
2366         display.lockActiveWindow = true;
2367         long code = callWindowProc (handle, OS.WM_NCLBUTTONDOWN, wParam, lParam);
2368         display.lockActiveWindow = false;
2369         Control focusControl = display.lastHittestControl;
2370         if (focusControl != null && !focusControl.isDisposed ()) {
2371                 focusControl.setFocus ();
2372         }
2373         display.lastHittestControl = null;
2374         display.ignoreRestoreFocus = false;
2375         return new LRESULT (code);
2376 }
2377
2378 @Override
2379 LRESULT WM_SETCURSOR (long wParam, long lParam) {
2380         /*
2381         * Feature in Windows.  When the shell is disabled
2382         * by a Windows standard dialog (like a MessageBox
2383         * or FileDialog), clicking in the shell does not
2384         * bring the shell or the dialog to the front. The
2385         * fix is to detect this case and bring the shell
2386         * forward.
2387         */
2388         int msg = OS.HIWORD (lParam);
2389         if (msg == OS.WM_LBUTTONDOWN) {
2390                 if (!Display.TrimEnabled) {
2391                         Shell modalShell = display.getModalShell ();
2392                         if (modalShell != null && !isActive ()) {
2393                                 long hwndModal = modalShell.handle;
2394                                 if (OS.IsWindowEnabled (hwndModal)) {
2395                                         OS.SetActiveWindow (hwndModal);
2396                                 }
2397                         }
2398                 }
2399                 if (!OS.IsWindowEnabled (handle)) {
2400                         long hwndPopup = OS.GetLastActivePopup (handle);
2401                         if (hwndPopup != 0 && hwndPopup != handle) {
2402                                 if (display.getControl (hwndPopup) == null) {
2403                                         if (OS.IsWindowEnabled (hwndPopup)) {
2404                                                 OS.SetActiveWindow (hwndPopup);
2405                                         }
2406                                 }
2407                         }
2408                 }
2409         }
2410         /*
2411         * When the shell that contains a cursor is disabled,
2412         * WM_SETCURSOR is called with HTERROR.  Normally,
2413         * when a control is disabled, the parent will get
2414         * mouse and cursor events.  In the case of a disabled
2415         * shell, there is no enabled parent.  In order to
2416         * show the cursor when a shell is disabled, it is
2417         * necessary to override WM_SETCURSOR when called
2418         * with HTERROR to set the cursor but only when the
2419         * mouse is in the client area of the shell.
2420         */
2421         int hitTest = (short) OS.LOWORD (lParam);
2422         if (hitTest == OS.HTERROR) {
2423                 if (!getEnabled ()) {
2424                         Control control = display.getControl (wParam);
2425                         if (control == this && cursor != null) {
2426                                 POINT pt = new POINT ();
2427                                 int pos = OS.GetMessagePos ();
2428                                 OS.POINTSTOPOINT (pt, pos);
2429                                 OS.ScreenToClient (handle, pt);
2430                                 RECT rect = new RECT ();
2431                                 OS.GetClientRect (handle, rect);
2432                                 if (OS.PtInRect (rect, pt)) {
2433                                         OS.SetCursor (cursor.handle);
2434                                         switch (msg) {
2435                                                 case OS.WM_LBUTTONDOWN:
2436                                                 case OS.WM_RBUTTONDOWN:
2437                                                 case OS.WM_MBUTTONDOWN:
2438                                                 case OS.WM_XBUTTONDOWN:
2439                                                         OS.MessageBeep (OS.MB_OK);
2440                                         }
2441                                         return LRESULT.ONE;
2442                                 }
2443                         }
2444                 }
2445         }
2446         return super.WM_SETCURSOR (wParam, lParam);
2447 }
2448
2449 @Override
2450 LRESULT WM_SHOWWINDOW (long wParam, long lParam) {
2451         LRESULT result = super.WM_SHOWWINDOW (wParam, lParam);
2452         if (result != null) return result;
2453         /*
2454         * Bug in Windows.  If the shell is hidden while the parent
2455         * is iconic,  Windows shows the shell when the parent is
2456         * deiconified.  This does not happen if the shell is hidden
2457         * while the parent is not an icon.  The fix is to track
2458         * visible state for the shell and refuse to show the shell
2459         * when the parent is shown.
2460         */
2461         if (lParam == OS.SW_PARENTOPENING) {
2462                 Control control = this;
2463                 while (control != null) {
2464                         Shell shell = control.getShell ();
2465                         if (!shell.showWithParent) return LRESULT.ZERO;
2466                         control = control.parent;
2467                 }
2468         }
2469         return result;
2470 }
2471
2472 @Override
2473 LRESULT WM_WINDOWPOSCHANGING (long wParam, long lParam) {
2474         LRESULT result = super.WM_WINDOWPOSCHANGING (wParam,lParam);
2475         if (result != null) return result;
2476         WINDOWPOS lpwp = new WINDOWPOS ();
2477         OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
2478         if ((lpwp.flags & OS.SWP_NOSIZE) == 0) {
2479                 lpwp.cx = Math.max (lpwp.cx, minWidth);
2480                 int trim = SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX;
2481                 if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
2482                         lpwp.cx = Math.max (lpwp.cx, OS.GetSystemMetrics (OS.SM_CXMINTRACK));
2483                 }
2484                 lpwp.cy = Math.max (lpwp.cy, minHeight);
2485                 if ((style & SWT.NO_TRIM) == 0 && (style & trim) != 0) {
2486                         if ((style & SWT.RESIZE) != 0) {
2487                                 lpwp.cy = Math.max (lpwp.cy, OS.GetSystemMetrics (OS.SM_CYMINTRACK));
2488                         } else {
2489                                 RECT rect = new RECT ();
2490                                 int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
2491                                 int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
2492                                 OS.AdjustWindowRectEx (rect, bits1, false, bits2);
2493                                 lpwp.cy = Math.max (lpwp.cy, rect.bottom - rect.top);
2494                         }
2495                 }
2496                 OS.MoveMemory (lParam, lpwp, WINDOWPOS.sizeof);
2497         }
2498         return result;
2499 }
2500 }