Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/eclipse/swt/widgets/Shell.java


1   /*******************************************************************************
2    * Copyright (c) 2000, 2004 IBM Corporation and others.
3    * All rights reserved. This program and the accompanying materials
4    * are made available under the terms of the Common Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/cpl-v10.html
7    * 
8    * Contributors:
9    *     IBM Corporation - initial API and implementation
10   *******************************************************************************/
11  package org.eclipse.swt.widgets;
12  
13  
14  import org.eclipse.swt.*;
15  import org.eclipse.swt.internal.*;
16  import org.eclipse.swt.internal.gtk.*;
17  import org.eclipse.swt.graphics.*;
18  import org.eclipse.swt.events.*;
19  
20  /**
21   * Instances of this class represent the "windows"
22   * which the desktop or "window manager" is managing.
23   * Instances that do not have a parent (that is, they
24   * are built using the constructor, which takes a 
25   * <code>Display</code> as the argument) are described
26   * as <em>top level</em> shells. Instances that do have
27   * a parent are described as <em>secondary</em> or
28   * <em>dialog</em> shells.
29   * <p>
30   * Instances are always displayed in one of the maximized, 
31   * minimized or normal states:
32   * <ul>
33   * <li>
34   * When an instance is marked as <em>maximized</em>, the
35   * window manager will typically resize it to fill the
36   * entire visible area of the display, and the instance
37   * is usually put in a state where it can not be resized 
38   * (even if it has style <code>RESIZE</code>) until it is
39   * no longer maximized.
40   * </li><li>
41   * When an instance is in the <em>normal</em> state (neither
42   * maximized or minimized), its appearance is controlled by
43   * the style constants which were specified when it was created
44   * and the restrictions of the window manager (see below).
45   * </li><li>
46   * When an instance has been marked as <em>minimized</em>,
47   * its contents (client area) will usually not be visible,
48   * and depending on the window manager, it may be
49   * "iconified" (that is, replaced on the desktop by a small
50   * simplified representation of itself), relocated to a
51   * distinguished area of the screen, or hidden. Combinations
52   * of these changes are also possible.
53   * </li>
54   * </ul>
55   * </p>
56   * <p>
57   * Note: The styles supported by this class must be treated
58   * as <em>HINT</em>s, since the window manager for the
59   * desktop on which the instance is visible has ultimate
60   * control over the appearance and behavior of decorations
61   * and modality. For example, some window managers only
62   * support resizable windows and will always assume the
63   * RESIZE style, even if it is not set. In addition, if a
64   * modality style is not supported, it is "upgraded" to a
65   * more restrictive modality style that is supported. For
66   * example, if <code>PRIMARY_MODAL</code> is not supported,
67   * it would be upgraded to <code>APPLICATION_MODAL</code>.
68   * <dl>
69   * <dt><b>Styles:</b></dt>
70   * <dd>BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE</dd>
71   * <dd>APPLICATION_MODAL, MODELESS, PRIMARY_MODAL, SYSTEM_MODAL</dd>
72   * <dt><b>Events:</b></dt>
73   * <dd>Activate, Close, Deactivate, Deiconify, Iconify</dd>
74   * </dl>
75   * Class <code>SWT</code> provides two "convenience constants"
76   * for the most commonly required style combinations:
77   * <dl>
78   * <dt><code>SHELL_TRIM</code></dt>
79   * <dd>
80   * the result of combining the constants which are required
81   * to produce a typical application top level shell: (that 
82   * is, <code>CLOSE | TITLE | MIN | MAX | RESIZE</code>)
83   * </dd>
84   * <dt><code>DIALOG_TRIM</code></dt>
85   * <dd>
86   * the result of combining the constants which are required
87   * to produce a typical application dialog shell: (that 
88   * is, <code>TITLE | CLOSE | BORDER</code>)
89   * </dd>
90   * </dl>
91   * </p>
92   * <p>
93   * Note: Only one of the styles APPLICATION_MODAL, MODELESS, 
94   * PRIMARY_MODAL and SYSTEM_MODAL may be specified.
95   * </p><p>
96   * IMPORTANT: This class is not intended to be subclassed.
97   * </p>
98   *
99   * @see Decorations
100  * @see SWT
101  */
102 public class Shell extends Decorations {
103   long /*int*/ shellHandle, tooltipsHandle;
104   boolean hasFocus, mapped;
105   int oldX, oldY, oldWidth, oldHeight;
106   Control lastActive;
107   Region region;
108 
109 /**
110  * Constructs a new instance of this class. This is equivalent
111  * to calling <code>Shell((Display) null)</code>.
112  *
113  * @exception SWTException <ul>
114  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
115  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
116  * </ul>
117  */
118 public Shell () {
119   this ((Display) null);
120 }
121 /**
122  * Constructs a new instance of this class given only the style
123  * value describing its behavior and appearance. This is equivalent
124  * to calling <code>Shell((Display) null, style)</code>.
125  * <p>
126  * The style value is either one of the style constants defined in
127  * class <code>SWT</code> which is applicable to instances of this
128  * class, or must be built by <em>bitwise OR</em>'ing together 
129  * (that is, using the <code>int</code> "|" operator) two or more
130  * of those <code>SWT</code> style constants. The class description
131  * lists the style constants that are applicable to the class.
132  * Style bits are also inherited from superclasses.
133  * </p>
134  *
135  * @param style the style of control to construct
136  *
137  * @exception SWTException <ul>
138  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
139  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
140  * </ul>
141  * 
142  * @see SWT#BORDER
143  * @see SWT#CLOSE
144  * @see SWT#MIN
145  * @see SWT#MAX
146  * @see SWT#RESIZE
147  * @see SWT#TITLE
148  * @see SWT#NO_TRIM
149  * @see SWT#SHELL_TRIM
150  * @see SWT#DIALOG_TRIM
151  * @see SWT#MODELESS
152  * @see SWT#PRIMARY_MODAL
153  * @see SWT#APPLICATION_MODAL
154  * @see SWT#SYSTEM_MODAL
155  */
156 public Shell (int style) {
157   this ((Display) null, style);
158 }
159 
160 /**
161  * Constructs a new instance of this class given only the display
162  * to create it on. It is created with style <code>SWT.SHELL_TRIM</code>.
163  * <p>
164  * Note: Currently, null can be passed in for the display argument.
165  * This has the effect of creating the shell on the currently active
166  * display if there is one. If there is no current display, the 
167  * shell is created on a "default" display. <b>Passing in null as
168  * the display argument is not considered to be good coding style,
169  * and may not be supported in a future release of SWT.</b>
170  * </p>
171  *
172  * @param display the display to create the shell on
173  *
174  * @exception SWTException <ul>
175  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
176  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
177  * </ul>
178  */
179 public Shell (Display display) {
180   this (display, SWT.SHELL_TRIM);
181 }
182 /**
183  * Constructs a new instance of this class given the display
184  * to create it on and a style value describing its behavior
185  * and appearance.
186  * <p>
187  * The style value is either one of the style constants defined in
188  * class <code>SWT</code> which is applicable to instances of this
189  * class, or must be built by <em>bitwise OR</em>'ing together 
190  * (that is, using the <code>int</code> "|" operator) two or more
191  * of those <code>SWT</code> style constants. The class description
192  * lists the style constants that are applicable to the class.
193  * Style bits are also inherited from superclasses.
194  * </p><p>
195  * Note: Currently, null can be passed in for the display argument.
196  * This has the effect of creating the shell on the currently active
197  * display if there is one. If there is no current display, the 
198  * shell is created on a "default" display. <b>Passing in null as
199  * the display argument is not considered to be good coding style,
200  * and may not be supported in a future release of SWT.</b>
201  * </p>
202  *
203  * @param display the display to create the shell on
204  * @param style the style of control to construct
205  *
206  * @exception SWTException <ul>
207  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
208  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
209  * </ul>
210  * 
211  * @see SWT#BORDER
212  * @see SWT#CLOSE
213  * @see SWT#MIN
214  * @see SWT#MAX
215  * @see SWT#RESIZE
216  * @see SWT#TITLE
217  * @see SWT#NO_TRIM
218  * @see SWT#SHELL_TRIM
219  * @see SWT#DIALOG_TRIM
220  * @see SWT#MODELESS
221  * @see SWT#PRIMARY_MODAL
222  * @see SWT#APPLICATION_MODAL
223  * @see SWT#SYSTEM_MODAL
224  */
225 public Shell (Display display, int style) {
226   this (display, null, style, 0);
227 }
228 
229 Shell (Display display, Shell parent, int style, long /*int*/ handle) {
230   super ();
231   checkSubclass ();
232   if (display == null) display = Display.getCurrent ();
233   if (display == null) display = Display.getDefault ();
234   if (!display.isValidThread ()) {
235     error (SWT.ERROR_THREAD_INVALID_ACCESS);
236   }
237   this.style = checkStyle (style);
238   this.parent = parent;
239   this.display = display;
240   this.handle = handle;
241   createWidget (0);
242 }
243 
244 /**
245  * Constructs a new instance of this class given only its
246  * parent. It is created with style <code>SWT.DIALOG_TRIM</code>.
247  * <p>
248  * Note: Currently, null can be passed in for the parent.
249  * This has the effect of creating the shell on the currently active
250  * display if there is one. If there is no current display, the 
251  * shell is created on a "default" display. <b>Passing in null as
252  * the parent is not considered to be good coding style,
253  * and may not be supported in a future release of SWT.</b>
254  * </p>
255  *
256  * @param parent a shell which will be the parent of the new instance
257  *
258  * @exception IllegalArgumentException <ul>
259  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
260  * </ul>
261  * @exception SWTException <ul>
262  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
263  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
264  * </ul>
265  */
266 public Shell (Shell parent) {
267   this (parent, SWT.DIALOG_TRIM);
268 }
269 
270 /**
271  * Constructs a new instance of this class given its parent
272  * and a style value describing its behavior and appearance.
273  * <p>
274  * The style value is either one of the style constants defined in
275  * class <code>SWT</code> which is applicable to instances of this
276  * class, or must be built by <em>bitwise OR</em>'ing together 
277  * (that is, using the <code>int</code> "|" operator) two or more
278  * of those <code>SWT</code> style constants. The class description
279  * lists the style constants that are applicable to the class.
280  * Style bits are also inherited from superclasses.
281  * </p><p>
282  * Note: Currently, null can be passed in for the parent.
283  * This has the effect of creating the shell on the currently active
284  * display if there is one. If there is no current display, the 
285  * shell is created on a "default" display. <b>Passing in null as
286  * the parent is not considered to be good coding style,
287  * and may not be supported in a future release of SWT.</b>
288  * </p>
289  *
290  * @param parent a shell which will be the parent of the new instance
291  * @param style the style of control to construct
292  *
293  * @exception SWTException <ul>
294  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
295  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
296  * </ul>
297  * 
298  * @see SWT#BORDER
299  * @see SWT#CLOSE
300  * @see SWT#MIN
301  * @see SWT#MAX
302  * @see SWT#RESIZE
303  * @see SWT#TITLE
304  * @see SWT#NO_TRIM
305  * @see SWT#SHELL_TRIM
306  * @see SWT#DIALOG_TRIM
307  * @see SWT#MODELESS
308  * @see SWT#PRIMARY_MODAL
309  * @see SWT#APPLICATION_MODAL
310  * @see SWT#SYSTEM_MODAL
311  */
312 public Shell (Shell parent, int style) {
313   this (parent != null ? parent.display : null, parent, style, 0);
314 }
315 
316 public static Shell gtk_new (Display display, long /*int*/ handle) {
317   return new Shell (display, null, SWT.NO_TRIM, handle);
318 }
319 
320 static int checkStyle (int style) {
321   style = Decorations.checkStyle (style);
322   if ((style & SWT.ON_TOP) != 0) style &= ~SWT.SHELL_TRIM;
323   int mask = SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.PRIMARY_MODAL;
324   int bits = style & ~mask;
325   if ((style & SWT.SYSTEM_MODAL) != 0) return bits | SWT.SYSTEM_MODAL;
326   if ((style & SWT.APPLICATION_MODAL) != 0) return bits | SWT.APPLICATION_MODAL;
327   if ((style & SWT.PRIMARY_MODAL) != 0) return bits | SWT.PRIMARY_MODAL;
328   return bits;
329 }
330 
331 /**
332  * Adds the listener to the collection of listeners who will
333  * be notified when operations are performed on the receiver,
334  * by sending the listener one of the messages defined in the
335  * <code>ShellListener</code> interface.
336  *
337  * @param listener the listener which should be notified
338  *
339  * @exception IllegalArgumentException <ul>
340  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
341  * </ul>
342  * @exception SWTException <ul>
343  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
344  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
345  * </ul>
346  *
347  * @see ShellListener
348  * @see #removeShellListener
349  */
350 public void addShellListener (ShellListener listener) {
351   checkWidget();
352   if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
353   TypedListener typedListener = new TypedListener (listener);
354   addListener (SWT.Close,typedListener);
355   addListener (SWT.Iconify,typedListener);
356   addListener (SWT.Deiconify,typedListener);
357   addListener (SWT.Activate, typedListener);
358   addListener (SWT.Deactivate, typedListener);
359 }
360 
361 void adjustTrim () {
362   int [] width = new int [1], height = new int [1];
363   OS.gtk_window_get_size (shellHandle, width, height);
364   long /*int*/ window = OS.GTK_WIDGET_WINDOW (shellHandle);
365   GdkRectangle rect = new GdkRectangle ();
366   OS.gdk_window_get_frame_extents (window, rect);
367   int trimWidth = Math.max (0, rect.width - width [0]);
368   int trimHeight = Math.max (0, rect.height - height [0]);
369   boolean hasTitle = false, hasResize = false, hasBorder = false;
370   if ((style & SWT.NO_TRIM) == 0) {
371     hasTitle = (style & (SWT.MIN | SWT.MAX | SWT.TITLE | SWT.MENU)) != 0;
372     hasResize = (style & SWT.RESIZE) != 0;
373     hasBorder = (style & SWT.BORDER) != 0;
374   }
375   if (hasTitle) {
376     if (hasResize)  {
377       display.titleResizeTrimWidth = trimWidth;
378       display.titleResizeTrimHeight = trimHeight;
379       return;
380     }
381     if (hasBorder) {
382       display.titleBorderTrimWidth = trimWidth;
383       display.titleBorderTrimHeight = trimHeight;
384       return;
385     }
386     display.titleTrimWidth = trimWidth;
387     display.titleTrimHeight = trimHeight;
388     return;
389   }
390   if (hasResize) {
391     display.resizeTrimWidth = trimWidth;
392     display.resizeTrimHeight = trimHeight;
393     return;
394   }
395   if (hasBorder) {
396     display.borderTrimWidth = trimWidth;
397     display.borderTrimHeight = trimHeight;
398     return;
399   }
400 }
401 
402 void bringToTop (boolean force) {
403   if (!OS.GTK_WIDGET_VISIBLE (shellHandle)) return; 
404   if (hasFocus) return;
405   Shell shell = display.getActiveShell ();
406   if (!force) {
407     if (shell == null) return;
408     long /*int*/ focusHandle = OS.gtk_window_get_focus (shell.shellHandle);
409     if (focusHandle != 0) {
410       if (!OS.GTK_WIDGET_HAS_FOCUS (focusHandle)) return;
411     }
412   }
413   if (shell != null) shell.hasFocus = false;
414   /*
415   * Feature in GTK.  When the shell is an override redirect
416   * window, gdk_window_focus() does not give focus to the
417   * window.  The fix is to use XSetInputFocus() to force
418   * the focus.
419   */
420   long /*int*/ window = OS.GTK_WIDGET_WINDOW (shellHandle);
421   if ((style & SWT.ON_TOP) != 0 && OS.GDK_WINDOWING_X11 ()) {
422     long /*int*/ xDisplay = OS.gdk_x11_drawable_get_xdisplay (window);
423     long /*int*/ xWindow = OS.gdk_x11_drawable_get_xid (window);
424     OS.gdk_error_trap_push ();
425     OS.XSetInputFocus (xDisplay, xWindow, OS.RevertToParent, OS.gtk_get_current_event_time ());
426     OS.gdk_error_trap_pop ();
427   } else {
428     OS.gdk_window_focus (window, OS.gtk_get_current_event_time ());
429   }
430   hasFocus = true;
431 }
432 
433 /**
434  * Requests that the window manager close the receiver in
435  * the same way it would be closed when the user clicks on
436  * the "close box" or performs some other platform specific
437  * key or mouse combination that indicates the window
438  * should be removed.
439  *
440  * @exception SWTException <ul>
441  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
442  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
443  * </ul>
444  *
445  * @see SWT#Close
446  * @see #dispose
447  */
448 public void close () {
449   checkWidget ();
450   closeWidget ();
451 }
452 void closeWidget () {
453   if (!isEnabled()) return;
454   Event event = new Event ();
455   sendEvent (SWT.Close, event);
456   if (event.doit && !isDisposed ()) dispose ();
457 }
458 
459 public Rectangle computeTrim (int x, int y, int width, int height) {
460   checkWidget();
461   Rectangle trim = super.computeTrim (x, y, width, height);
462   int trimWidth = trimWidth (), trimHeight = trimHeight ();
463   trim.x -= trimWidth / 2; trim.y -= trimHeight - (trimWidth / 2);
464   trim.width += trimWidth; trim.height += trimHeight;
465   if (menuBar != null) {
466     int menuBarHeight = OS.GTK_WIDGET_HEIGHT (menuBar.handle);
467     trim.y -= menuBarHeight;
468     trim.height += menuBarHeight;
469   }
470   return trim;
471 }
472 
473 void createHandle (int index) {
474   state |= HANDLE | CANVAS;
475   if (handle == 0) {
476     int type = OS.GTK_WINDOW_TOPLEVEL;
477     if ((style & SWT.ON_TOP) != 0) type = OS.GTK_WINDOW_POPUP;
478     shellHandle = OS.gtk_window_new (type);
479   } else {
480     shellHandle = OS.gtk_plug_new (handle);
481   }
482   if (shellHandle == 0) SWT.error (SWT.ERROR_NO_HANDLES);
483   if (parent != null) {
484     OS.gtk_window_set_transient_for (shellHandle, parent.topHandle ());
485     OS.gtk_window_set_destroy_with_parent (shellHandle, true);
486     int orientations = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
487     if (!((style & ~orientations) == SWT.NONE || (style & (SWT.NO_TRIM | SWT.ON_TOP)) != 0)) {
488       OS.gtk_window_set_type_hint (shellHandle, OS.GDK_WINDOW_TYPE_HINT_DIALOG);
489     }
490   }
491   /*
492   * Feature in GTK.  The window size must be set when the window
493   * is created or it will not be allowed to be resized smaller that the
494   * initial size by the user.  The fix is to set the size to zero.
495   */
496   if ((style & SWT.RESIZE) != 0) {
497     OS.gtk_widget_set_size_request (shellHandle, 0, 0);
498     OS.gtk_window_set_resizable (shellHandle, true);
499   } else {
500     OS.gtk_window_set_resizable (shellHandle, false);
501   }
502   createHandle (index, shellHandle, true);
503   OS.gtk_widget_realize (shellHandle);
504   long /*int*/ window = OS.GTK_WIDGET_WINDOW (shellHandle);
505   int decorations = 0;
506   if ((style & SWT.NO_TRIM) == 0) {
507     if ((style & SWT.MIN) != 0) decorations |= OS.GDK_DECOR_MINIMIZE;
508     if ((style & SWT.MAX) != 0) decorations |= OS.GDK_DECOR_MAXIMIZE;
509     if ((style & SWT.RESIZE) != 0) decorations |= OS.GDK_DECOR_RESIZEH;
510     if ((style & SWT.BORDER) != 0) decorations |= OS.GDK_DECOR_BORDER;
511     if ((style & SWT.MENU) != 0) decorations |= OS.GDK_DECOR_MENU;
512     if ((style & SWT.TITLE) != 0) decorations |= OS.GDK_DECOR_TITLE;
513     /*
514     * Feature in GTK.  Under some Window Managers (Sawmill), in order
515     * to get any border at all from the window manager it is necessary to
516     * set GDK_DECOR_BORDER.  The fix is to force these bits when any
517     * kind of border is requested.
518     */
519     if ((style & SWT.RESIZE) != 0) decorations |= OS.GDK_DECOR_BORDER;
520   }
521   OS.gdk_window_set_decorations (window, decorations);
522   OS.gtk_window_set_title (shellHandle, new byte [1]);
523   if ((style & SWT.ON_TOP) != 0) {
524     OS.gdk_window_set_override_redirect (window, true);
525   }
526   if ((style & (SWT.NO_TRIM | SWT.BORDER | SWT.RESIZE)) == 0) {
527     OS.gtk_container_set_border_width (shellHandle, 1);
528     GdkColor color = new GdkColor ();
529     OS.gtk_style_get_black (OS.gtk_widget_get_style (shellHandle), color);
530     OS.gtk_widget_modify_bg (shellHandle,  OS.GTK_STATE_NORMAL, color);
531   }
532   int bits = SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
533   boolean modal = (style & bits) != 0;
534   //TEMPORARY CODE
535   if ((style & SWT.ON_TOP) == 0) modal |= (parent != null && (parent.style & bits) != 0);
536   OS.gtk_window_set_modal (shellHandle, modal);
537 }
538 
539 boolean hasBorder () {
540   return false;
541 }
542 
543 void hookEvents () {
544   super.hookEvents ();
545   long /*int*/ shellMapProc = display.shellMapProc;
546   long /*int*/ windowProc3 = display.windowProc3;
547   OS.g_signal_connect (shellHandle, OS.map_event, windowProc3, MAP_EVENT);
548   OS.g_signal_connect (shellHandle, OS.unmap_event, windowProc3, UNMAP_EVENT);
549   OS.g_signal_connect (shellHandle, OS.window_state_event, windowProc3, WINDOW_STATE_EVENT);
550   OS.g_signal_connect (shellHandle, OS.size_allocate, windowProc3, SIZE_ALLOCATE);
551   OS.g_signal_connect (shellHandle, OS.configure_event, windowProc3, CONFIGURE_EVENT);
552   OS.g_signal_connect (shellHandle, OS.delete_event, windowProc3, DELETE_EVENT);
553   OS.g_signal_connect (shellHandle, OS.focus_in_event, windowProc3, FOCUS_IN_EVENT);
554   OS.g_signal_connect (shellHandle, OS.focus_out_event, windowProc3, FOCUS_OUT_EVENT);
555   OS.g_signal_connect (shellHandle, OS.map_event, shellMapProc, 0);
556   OS.g_signal_connect (shellHandle, OS.enter_notify_event, windowProc3, ENTER_NOTIFY_EVENT);
557   if (OS.GDK_WINDOWING_X11 ()) {
558     long /*int*/ window = OS.GTK_WIDGET_WINDOW (shellHandle);
559     OS.gdk_window_add_filter  (window, display.filterProc, shellHandle);
560   }
561 }
562 
563 public boolean isEnabled () {
564   checkWidget ();
565   return getEnabled ();
566 }
567 
568 public boolean isVisible () {
569   checkWidget();
570   return getVisible ();
571 }
572 
573 void register () {
574   super.register ();
575   display.addWidget (shellHandle, this);
576 }
577 
578 void releaseChild () {
579   /* Do nothing */
580 }
581 
582 long /*int*/ topHandle () {
583   return shellHandle;
584 }
585 
586 long /*int*/ filterProc (long /*int*/ xEvent, long /*int*/ gdkEvent, long /*int*/ data) {
587   /*
588   * Bug in GTK.  When a shell that has no window manager trimmings
589   * is given focus, GTK gets stuck in "focus follows pointer" mode when
590   * the pointer is within the shell and its parent when the shell is disposed.
591   * The fix is to modify the X events that cause this to happen.
592   */
593   XFocusChangeEvent focusEvent = new XFocusChangeEvent ();
594   OS.memmove (focusEvent, xEvent, 4);
595   switch (focusEvent.type) {
596     case OS.FocusIn: {
597       OS.memmove (focusEvent, xEvent, XFocusChangeEvent.sizeof);
598       if (focusEvent.detail == OS.NotifyPointer) {
599         focusEvent.detail = OS.NotifyNonlinear;
600         OS.memmove (xEvent, focusEvent, XFocusChangeEvent.sizeof);
601       }
602       break;
603     }
604     case OS.EnterNotify: {
605       XCrossingEvent crossingEvent = new XCrossingEvent ();
606       OS.memmove (crossingEvent, xEvent, XCrossingEvent.sizeof);
607       if (crossingEvent.focus) {
608         crossingEvent.focus = false;
609         OS.memmove (xEvent, crossingEvent, XCrossingEvent.sizeof);
610       }
611       break;
612     }
613   }
614   return 0;
615 }
616 
617 void fixShell (Shell newShell, Control control) {
618   if (this == newShell) return;
619   if (control == lastActive) setActiveControl (null);
620   if (tooltipsHandle != 0) {
621     setToolTipText (control.handle, null);
622   }
623   newShell.setToolTipText (control.handle, control.toolTipText);
624 }
625 
626 public Point getLocation () {
627   checkWidget ();
628   int [] x = new int [1], y = new int [1];
629   OS.gtk_window_get_position (shellHandle, x,y);
630   return new Point (x [0], y [0]);
631 }
632 
633 public Point getSize () {
634   checkWidget ();
635   int width = OS.GTK_WIDGET_WIDTH (scrolledHandle);
636   int height = OS.GTK_WIDGET_HEIGHT (scrolledHandle);
637   if (menuBar != null)  {
638     long /*int*/ barHandle = menuBar.handle;
639     height += OS.GTK_WIDGET_HEIGHT (barHandle);
640   }
641   return new Point (width + trimWidth (), height + trimHeight ());
642 }
643 
644 /** 
645  * Returns the region that defines the shape of the shell,
646  * or null if the shell has the default shape.
647  *
648  * @return the region that defines the shape of the shell (or null)
649  *  
650  * @exception SWTException <ul>
651  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
652  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
653  * </ul>
654  *
655  * @since 3.0
656  *
657  */
658 public Region getRegion () {
659   checkWidget ();
660   return region;
661 }
662 
663 /**
664  * Returns the receiver's input method editor mode. This
665  * will be the result of bitwise OR'ing together one or
666  * more of the following constants defined in class
667  * <code>SWT</code>:
668  * <code>NONE</code>, <code>ROMAN</code>, <code>DBCS</code>, 
669  * <code>PHONETIC</code>, <code>NATIVE</code>, <code>ALPHA</code>.
670  *
671  * @return the IME mode
672  *
673  * @exception SWTException <ul>
674  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
675  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
676  * </ul>
677  *
678  * @see SWT
679  */
680 public int getImeInputMode () {
681   checkWidget();
682   return SWT.NONE;
683 }
684 
685 Shell _getShell () {
686   return this;
687 }
688 /**
689  * Returns an array containing all shells which are 
690  * descendents of the receiver.
691  * <p>
692  * @return the dialog shells
693  *
694  * @exception SWTException <ul>
695  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
696  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
697  * </ul>
698  */
699 public Shell [] getShells () {
700   checkWidget();
701   int count = 0;
702   Shell [] shells = display.getShells ();
703   for (int i=0; i<shells.length; i++) {
704     Control shell = shells [i];
705     do {
706       shell = shell.getParent ();
707     } while (shell != null && shell != this);
708     if (shell == this) count++;
709   }
710   int index = 0;
711   Shell [] result = new Shell [count];
712   for (int i=0; i<shells.length; i++) {
713     Control shell = shells [i];
714     do {
715       shell = shell.getParent ();
716     } while (shell != null && shell != this);
717     if (shell == this) {
718       result [index++] = shells [i];
719     }
720   }
721   return result;
722 }
723 
724 long /*int*/ gtk_configure_event (long /*int*/ widget, long /*int*/ event) {
725   int [] x = new int [1], y = new int [1];
726   OS.gtk_window_get_position (shellHandle, x, y);
727   if (oldX != x [0] || oldY != y [0]) {
728     oldX = x [0];
729     oldY = y [0];
730     sendEvent (SWT.Move);
731   }
732   return 0;
733 }
734 
735 long /*int*/ gtk_delete_event (long /*int*/ widget, long /*int*/ event) {
736   closeWidget ();
737   return 1;
738 }
739 
740 long /*int*/ gtk_enter_notify_event (long /*int*/ widget, long /*int*/ event) {
741   if (widget != shellHandle) {
742     return super.gtk_enter_notify_event (widget, event);
743   }
744   return 0;
745 }
746 
747 long /*int*/ gtk_focus (long /*int*/ widget, long /*int*/ directionType) {
748   switch ((int)/*64*/directionType) {
749     case OS.GTK_DIR_TAB_FORWARD:
750     case OS.GTK_DIR_TAB_BACKWARD:
751       Control control = display.getFocusControl ();
752       if (control != null) {
753         if ((control.state & CANVAS) != 0 && (control.style & SWT.EMBEDDED) != 0) {
754           int traversal = directionType == OS.GTK_DIR_TAB_FORWARD ? SWT.TRAVERSE_TAB_NEXT : SWT.TRAVERSE_TAB_PREVIOUS;
755           control.traverse (traversal);
756           return 1;
757         }
758       }
759       break;
760   }
761   return super.gtk_focus (widget, directionType);
762 }
763 
764 long /*int*/ gtk_focus_in_event (long /*int*/ widget, long /*int*/ event) {
765   if (widget != shellHandle) {
766     return super.gtk_focus_in_event (widget, event);
767   }
768   if (tooltipsHandle != 0) OS.gtk_tooltips_enable (tooltipsHandle);
769   hasFocus = true;
770   sendEvent (SWT.Activate);
771   return 0;
772 }
773 
774 long /*int*/ gtk_focus_out_event (long /*int*/ widget, long /*int*/ event) {
775   if (widget != shellHandle) {
776     return super.gtk_focus_out_event (widget, event);
777   }
778   if (tooltipsHandle != 0) OS.gtk_tooltips_disable (tooltipsHandle);
779   hasFocus = false;
780   sendEvent (SWT.Deactivate);
781   return 0;
782 }
783 
784 long /*int*/ gtk_map_event (long /*int*/ widget, long /*int*/ event) {
785   minimized = false;
786   sendEvent (SWT.Deiconify);
787   return 0;
788 }
789 
790 long /*int*/ gtk_size_allocate (long /*int*/ widget, long /*int*/ allocation) {
791   int [] width = new int [1], height = new int [1];
792   OS.gtk_window_get_size (shellHandle, width, height);
793   if (oldWidth != width [0] || oldHeight != height [0]) {
794     oldWidth = width [0];
795     oldHeight = height [0];
796     resizeBounds (width [0], height [0], true);
797   }
798   return 0;
799 }
800 
801 long /*int*/ gtk_unmap_event (long /*int*/ widget, long /*int*/ event) {
802   minimized = true;
803   sendEvent (SWT.Iconify);
804   return 0;
805 }
806 
807 long /*int*/ gtk_window_state_event (long /*int*/ widget, long /*int*/ event) {
808   GdkEventWindowState gdkEvent = new GdkEventWindowState ();
809   OS.memmove (gdkEvent, event, GdkEventWindowState.sizeof);
810   minimized = (gdkEvent.new_window_state & OS.GDK_WINDOW_STATE_ICONIFIED) != 0;
811   maximized = (gdkEvent.new_window_state & OS.GDK_WINDOW_STATE_MAXIMIZED) != 0;
812   return 0;
813 }
814 
815 /**
816  * Moves the receiver to the top of the drawing order for
817  * the display on which it was created (so that all other
818  * shells on that display, which are not the receiver's
819  * children will be drawn behind it), marks it visible,
820  * sets the focus and asks the window manager to make the
821  * shell active.
822  *
823  * @exception SWTException <ul>
824  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
825  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
826  * </ul>
827  *
828  * @see Control#moveAbove
829  * @see Control#setFocus
830  * @see Control#setVisible
831  * @see Display#getActiveShell
832  * @see Decorations#setDefaultButton
833  * @see Shell#setActive
834  * @see Shell#forceActive
835  */
836 public void open () {
837   checkWidget ();
838   setVisible (true);
839   bringToTop (false);
840   if (!restoreFocus ()) {
841     long /*int*/ focusHandle = OS.gtk_window_get_focus (shellHandle);
842     if (focusHandle == 0 || focusHandle == handle) {
843       if (!traverseGroup (true)) {
844         focusHandle = OS.gtk_window_get_focus (shellHandle);
845         if (focusHandle == 0) OS.gtk_widget_grab_focus (focusHandle ());
846       }
847     }
848   }
849 }
850 
851 /**
852  * Removes the listener from the collection of listeners who will
853  * be notified when operations are performed on the receiver.
854  *
855  * @param listener the listener which should no longer be notified
856  *
857  * @exception IllegalArgumentException <ul>
858  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
859  * </ul>
860  * @exception SWTException <ul>
861  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
862  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
863  * </ul>
864  *
865  * @see ShellListener
866  * @see #addShellListener
867  */
868 public void removeShellListener (ShellListener listener) {
869   checkWidget();
870   if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
871   if (eventTable == null) return;
872   eventTable.unhook (SWT.Close, listener);
873   eventTable.unhook (SWT.Iconify,listener);
874   eventTable.unhook (SWT.Deiconify,listener);
875   eventTable.unhook (SWT.Activate, listener);
876   eventTable.unhook (SWT.Deactivate, listener);
877 }
878 
879 /**
880  * Moves the receiver to the top of the drawing order for
881  * the display on which it was created (so that all other
882  * shells on that display, which are not the receiver's
883  * children will be drawn behind it) and asks the window
884  * manager to make the shell active.
885  *
886  * @exception SWTException <ul>
887  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
888  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
889  * </ul>
890  *
891  * @since 2.0
892  * @see Control#moveAbove
893  * @see Control#setFocus
894  * @see Control#setVisible
895  * @see Display#getActiveShell
896  * @see Decorations#setDefaultButton
897  * @see Shell#open
898  * @see Shell#setActive
899  */
900 public void setActive () {
901   checkWidget ();
902   bringToTop (false);
903 }
904 
905 void setActiveControl (Control control) {
906   if (control != null && control.isDisposed ()) control = null;
907   if (lastActive != null && lastActive.isDisposed ()) lastActive = null;
908   if (lastActive == control) return;
909   
910   /*
911   * Compute the list of controls to be activated and
912   * deactivated by finding the first common parent
913   * control.
914   */
915   Control [] activate = (control == null) ? new Control[0] : control.getPath ();
916   Control [] deactivate = (lastActive == null) ? new Control[0] : lastActive.getPath ();
917   lastActive = control;
918   int index = 0, length = Math.min (activate.length, deactivate.length);
919   while (index < length) {
920     if (activate [index] != deactivate [index]) break;
921     index++;
922   }
923   
924   /*
925   * It is possible (but unlikely), that application
926   * code could have destroyed some of the widgets. If
927   * this happens, keep processing those widgets that
928   * are not disposed.
929   */
930   for (int i=deactivate.length-1; i>=index; --i) {
931     if (!deactivate [i].isDisposed ()) {
932       deactivate [i].sendEvent (SWT.Deactivate);
933     }
934   }
935   for (int i=activate.length-1; i>=index; --i) {
936     if (!activate [i].isDisposed ()) {
937       activate [i].sendEvent (SWT.Activate);
938     }
939   }
940 }
941 
942 void resizeBounds (int width, int height, boolean notify) {
943   if (redrawWindow != 0) {
944     OS.gdk_window_resize (redrawWindow, width, height);
945   }
946   if (enableWindow != 0) {
947     OS.gdk_window_resize (enableWindow, width, height);
948   }
949   int border = OS.gtk_container_get_border_width (shellHandle);
950   int menuHeight = 0;
951   if (menuBar != null) {
952     long /*int*/ menuHandle = menuBar.handle;
953     OS.gtk_widget_set_size_request (menuHandle, -1, -1);
954     GtkRequisition requisition = new GtkRequisition ();
955     OS.gtk_widget_size_request (menuHandle, requisition);
956     menuHeight = requisition.height;
957     OS.gtk_widget_set_size_request (menuHandle, width - (border  * 2), menuHeight);
958     height = Math.max (1, height - menuHeight);
959   }
960   OS.gtk_fixed_move (fixedHandle, scrolledHandle, 0, menuHeight);
961   OS.gtk_widget_set_size_request (scrolledHandle, width - (border  * 2), height - (border  * 2));
962   OS.gtk_container_resize_children (fixedHandle);
963   if (notify) {
964     sendEvent (SWT.Resize);
965     if (layout != null) layout.layout (this, false);
966   }
967 }
968 
969 boolean setBounds (int x, int y, int width, int height, boolean move, boolean resize) {
970   if (move) {
971     int [] x_pos = new int [1], y_pos = new int [1];
972     OS.gtk_window_get_position (shellHandle, x_pos, y_pos);
973     OS.gtk_window_move (shellHandle, x, y);
974     if (x_pos [0] != x || y_pos [0] != y) {
975       oldX = x;
976       oldY = y;
977       sendEvent(SWT.Move);
978     }
979   }
980   if (resize) {
981     int [] w = new int [1], h = new int [1];
982     OS.gtk_window_get_size (shellHandle, w, h);
983     width = Math.max (1, width - trimWidth ());
984     height = Math.max (1, height - trimHeight ());
985     OS.gtk_window_resize (shellHandle, width, height);
986     boolean changed = width != oldWidth || height != oldHeight;
987     if (changed) {
988       oldWidth = width;
989       oldHeight = height;
990     }
991     resizeBounds (width, height, changed);
992   }
993   return move || resize;
994 }
995 
996 void setCursor (long /*int*/ cursor) {
997   if (enableWindow != 0) {
998     OS.gdk_window_set_cursor (enableWindow, cursor);
999     OS.gdk_flush ();
1000  }
1001  super.setCursor (cursor);
1002}
1003
1004public void setEnabled (boolean enabled) {
1005  checkWidget();
1006  if (((state & DISABLED) == 0) == enabled) return;
1007  Control control = null;
1008  boolean fixFocus = false;
1009  if (!enabled) {
1010    control = display.getFocusControl ();
1011    fixFocus = isFocusAncestor (control);
1012  }
1013  if (enabled) {
1014    state &= ~DISABLED;
1015  } else {
1016    state |= DISABLED;
1017  }
1018  enableWidget (enabled);
1019  if (enabled) {
1020    if (enableWindow != 0) {
1021      OS.gdk_window_set_user_data (enableWindow, 0);
1022      OS.gdk_window_destroy (enableWindow);
1023      enableWindow = 0;
1024    }
1025  } else {
1026    long /*int*/ parentHandle = shellHandle;
1027    OS.gtk_widget_realize (parentHandle);
1028    long /*int*/ window = OS.GTK_WIDGET_WINDOW (parentHandle);
1029    Rectangle rect = getBounds ();
1030    GdkWindowAttr attributes = new GdkWindowAttr ();
1031    attributes.width = rect.width;
1032    attributes.height = rect.height;
1033    attributes.event_mask = (0xFFFFFFFF & ~OS.ExposureMask);
1034    attributes.wclass = OS.GDK_INPUT_ONLY;
1035    attributes.window_type = OS.GDK_WINDOW_CHILD;
1036    enableWindow = OS.gdk_window_new (window, attributes, 0);
1037    if (enableWindow != 0) {
1038      if (cursor != null) {
1039        OS.gdk_window_set_cursor (enableWindow, cursor.handle);
1040        OS.gdk_flush ();
1041      }
1042      OS.gdk_window_set_user_data (enableWindow, parentHandle);
1043      OS.gdk_window_raise (enableWindow);
1044      OS.gdk_window_show (enableWindow);
1045    }
1046  }
1047  if (fixFocus) fixFocus (control);
1048  if (enabled && hasFocus) {
1049    if (!restoreFocus ()) traverseGroup (false);
1050  }
1051}
1052
1053/**
1054 * Sets the input method editor mode to the argument which 
1055 * should be the result of bitwise OR'ing together one or more
1056 * of the following constants defined in class <code>SWT</code>:
1057 * <code>NONE</code>, <code>ROMAN</code>, <code>DBCS</code>, 
1058 * <code>PHONETIC</code>, <code>NATIVE</code>, <code>ALPHA</code>.
1059 *
1060 * @param mode the new IME mode
1061 *
1062 * @exception SWTException <ul>
1063 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1064 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1065 * </ul>
1066 *
1067 * @see SWT
1068 */
1069public void setImeInputMode (int mode) {
1070  checkWidget();
1071}
1072
1073void setInitialSize () {
1074  Monitor monitor = getMonitor ();
1075  Rectangle rect = monitor.getClientArea ();
1076  int width = rect.width * 5 / 8;
1077  int height = rect.height * 5 / 8;
1078  OS.gtk_widget_set_size_request (scrolledHandle, width, height);
1079  OS.gtk_window_resize (shellHandle, width, height);
1080  OS.gtk_container_resize_children (fixedHandle);
1081}
1082
1083public void setMaximized (boolean maximized) {
1084  checkWidget();
1085  super.setMaximized (maximized);
1086  if (maximized) {
1087    OS.gtk_window_maximize (shellHandle);
1088  } else {
1089    OS.gtk_window_unmaximize (shellHandle);
1090  }
1091}
1092
1093public void setMenuBar (Menu menu) {
1094  checkWidget();
1095  if (menuBar == menu) return;
1096  boolean both = menu != null && menuBar != null;
1097  if (menu != null) {
1098    if ((menu.style & SWT.BAR) == 0) error (SWT.ERROR_MENU_NOT_BAR);
1099    if (menu.parent != this) error (SWT.ERROR_INVALID_PARENT);
1100  }
1101  if (menuBar != null) {
1102    long /*int*/ menuHandle = menuBar.handle;
1103    OS.gtk_widget_hide (menuHandle);
1104    destroyAccelGroup ();
1105  }
1106  menuBar = menu;
1107  if (menuBar != null) {
1108    long /*int*/ menuHandle = menu.handle;
1109    OS.gtk_widget_show (menuHandle);
1110    createAccelGroup ();
1111    menuBar.addAccelerators (accelGroup);
1112  }
1113  int [] width = new int [1], height = new int [1];
1114  OS.gtk_window_get_size (shellHandle, width, height);
1115  resizeBounds (width [0], height [0], !both);
1116}
1117
1118public void setMinimized (boolean minimized) {
1119  checkWidget();
1120  if (this.minimized == minimized) return;
1121  super.setMinimized (minimized);
1122  if (minimized) {
1123    OS.gtk_window_iconify (shellHandle);
1124  } else {
1125    OS.gtk_window_deiconify (shellHandle);
1126    bringToTop (false);
1127  }
1128}
1129
1130/**
1131 * Sets the shape of the shell to the region specified
1132 * by the argument.  When the argument is null, the
1133 * default shape of the shell is restored.  The shell
1134 * must be created with the style SWT.NO_TRIM in order
1135 * to specify a region.
1136 *
1137 * @param region the region that defines the shape of the shell (or null)
1138 *
1139 * @exception IllegalArgumentException <ul>
1140 *    <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</li>
1141 * </ul>  
1142 * @exception SWTException <ul>
1143 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1144 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1145 * </ul>
1146 *
1147 * @since 3.0
1148 *
1149 */
1150public void setRegion (Region region) {
1151  checkWidget ();
1152  if ((style & SWT.NO_TRIM) == 0) return;
1153  if (region != null && region.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
1154  long /*int*/ window = OS.GTK_WIDGET_WINDOW (shellHandle);
1155  long /*int*/ shape_region = (region == null) ? 0 : region.handle;
1156  OS.gdk_window_shape_combine_region (window, shape_region, 0, 0);
1157  this.region = region;
1158}
1159
1160public void setText (String string) {
1161  super.setText (string);
1162
1163  /* 
1164  * GTK bug 82013.  For some reason, if the title string
1165  * is less that 7 bytes long and is not terminated by
1166  * a space, some window managers occasionally draw
1167  * garbage after the last character in  the title.
1168  * The fix is to pad the title.
1169  */
1170  int length = string.length ();
1171  char [] chars = new char [Math.max (6, length) + 1];
1172  string.getChars (0, length , chars, 0);
1173  for (int i=length; i<chars.length; i++)  chars [i] = ' ';
1174  byte [] buffer = Converter.wcsToMbcs (null, chars, true);
1175  OS.gtk_window_set_title (shellHandle, buffer);
1176}
1177
1178public void setVisible (boolean visible) {
1179  checkWidget();
1180  if ((OS.GTK_WIDGET_MAPPED (shellHandle) == visible)) return;
1181  if (visible) {
1182    sendEvent (SWT.Show);
1183    if (isDisposed ()) return;
1184
1185    /*
1186    * In order to ensure that the shell is visible
1187    * and fully painted, dispatch events such as
1188    * GDK_MAP and GDK_CONFIGURE, until the GDK_MAP
1189    * event for the shell is received.
1190    */
1191    mapped = false;
1192    OS.gtk_widget_show (shellHandle);
1193    display.dispatchEvents = new int [] {
1194      OS.GDK_EXPOSE,
1195      OS.GDK_CONFIGURE,
1196      OS.GDK_MAP,
1197      OS.GDK_UNMAP,
1198      OS.GDK_NO_EXPOSE,
1199    };
1200    display.putGdkEvents();
1201    while (!isDisposed () && !mapped) {
1202      OS.gtk_main_iteration ();
1203    }
1204    display.dispatchEvents = null;
1205    if (isDisposed ()) return;
1206    update (true);
1207    if (isDisposed ()) return;
1208    adjustTrim ();
1209
1210    int mask = SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
1211    if ((style & mask) != 0) {
1212      OS.gdk_pointer_ungrab (OS.GDK_CURRENT_TIME);
1213    }
1214  } else {  
1215    OS.gtk_widget_hide (shellHandle);
1216    sendEvent (SWT.Hide);
1217  }
1218}
1219
1220void setZOrder (Control sibling, boolean above) {
1221   setZOrder (sibling, above, false);
1222}
1223
1224long /*int*/ shellMapProc (long /*int*/ handle, long /*int*/ arg0, long /*int*/ user_data) {
1225  mapped = true;
1226  display.dispatchEvents = null;
1227  return 0;
1228}
1229
1230boolean traverseEscape () {
1231  if (parent == null) return false;
1232  if (!isVisible () || !isEnabled ()) return false;
1233  close ();
1234  return true;
1235}
1236int trimHeight () {
1237  if ((style & SWT.NO_TRIM) != 0) return 0;
1238  boolean hasTitle = false, hasResize = false, hasBorder = false;
1239  hasTitle = (style & (SWT.MIN | SWT.MAX | SWT.TITLE | SWT.MENU)) != 0;
1240  hasResize = (style & SWT.RESIZE) != 0;
1241  hasBorder = (style & SWT.BORDER) != 0;
1242  if (hasTitle) {
1243    if (hasResize) return display.titleResizeTrimHeight;
1244    if (hasBorder) return display.titleBorderTrimHeight;
1245    return display.titleTrimHeight;
1246  }
1247  if (hasResize) return display.resizeTrimHeight;
1248  if (hasBorder) return display.borderTrimHeight;
1249  return 0;
1250}
1251
1252int trimWidth () {
1253  if ((style & SWT.NO_TRIM) != 0) return 0;
1254  boolean hasTitle = false, hasResize = false, hasBorder = false;
1255  hasTitle = (style & (SWT.MIN | SWT.MAX | SWT.TITLE | SWT.MENU)) != 0;
1256  hasResize = (style & SWT.RESIZE) != 0;
1257  hasBorder = (style & SWT.BORDER) != 0;
1258  if (hasTitle) {
1259    if (hasResize) return display.titleResizeTrimWidth;
1260    if (hasBorder) return display.titleBorderTrimWidth;
1261    return display.titleTrimWidth;
1262  }
1263  if (hasResize) return display.resizeTrimWidth;
1264  if (hasBorder) return display.borderTrimWidth;
1265  return 0;
1266}
1267
1268void deregister () {
1269  super.deregister ();
1270  display.removeWidget (shellHandle);
1271}
1272
1273public void dispose () {
1274  /*
1275  * Note:  It is valid to attempt to dispose a widget
1276  * more than once.  If this happens, fail silently.
1277  */
1278  if (isDisposed()) return;
1279
1280  /*
1281  * Feature in GTK.  When the active shell is disposed,
1282  * GTK assigns focus temporarily to the root window
1283  * unless it has previously been told to do otherwise.
1284  * The fix is to make the parent be the active top level
1285  * shell when the child shell is disposed.
1286  */
1287    OS.gtk_widget_hide (shellHandle);
1288    if (parent != null) {
1289      Shell activeShell = display.getActiveShell ();
1290      if (activeShell == this) {
1291        Shell shell = parent.getShell ();  
1292        shell.bringToTop (false);
1293      }
1294    }
1295  super.dispose ();
1296}
1297
1298/**
1299 * Moves the receiver to the top of the drawing order for
1300 * the display on which it was created (so that all other
1301 * shells on that display, which are not the receiver's
1302 * children will be drawn behind it) and forces the window
1303 * manager to make the shell active.
1304 *
1305 * @exception SWTException <ul>
1306 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1307 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1308 * </ul>
1309 *
1310 * @since 2.0
1311 * @see Control#moveAbove
1312 * @see Control#setFocus
1313 * @see Control#setVisible
1314 * @see Display#getActiveShell
1315 * @see Decorations#setDefaultButton
1316 * @see Shell#open
1317 * @see Shell#setActive
1318 */
1319public void forceActive () {
1320  checkWidget ();
1321  bringToTop (true);
1322}
1323
1324public Rectangle getBounds () {
1325  checkWidget ();
1326  int [] x = new int [1], y = new int [1];
1327  OS.gtk_window_get_position (shellHandle, x, y);
1328  int width = OS.GTK_WIDGET_WIDTH (scrolledHandle);
1329  int height = OS.GTK_WIDGET_HEIGHT (scrolledHandle);
1330  if (menuBar != null)  {
1331    long /*int*/ barHandle = menuBar.handle;
1332    height += OS.GTK_WIDGET_HEIGHT (barHandle);
1333  }
1334  return new Rectangle (x [0], y [0], width + trimWidth (), height + trimHeight ());
1335}
1336
1337void releaseHandle () {
1338  super.releaseHandle ();
1339  shellHandle = 0;
1340}
1341
1342void releaseShells () {
1343  Shell [] shells = getShells ();
1344  for (int i=0; i<shells.length; i++) {
1345    Shell shell = shells [i];
1346    if (!shell.isDisposed ()) shell.releaseResources ();
1347  }
1348}
1349
1350void releaseWidget () {
1351  releaseShells ();
1352  destroyAccelGroup ();
1353  super.releaseWidget ();
1354  if (tooltipsHandle != 0) OS.g_object_unref (tooltipsHandle);
1355  tooltipsHandle = 0;
1356  region = null;
1357  lastActive = null;
1358}
1359
1360void setToolTipText (long /*int*/ widget, String string) {
1361  byte [] buffer = null;
1362  if (string != null && string.length () > 0) {
1363    buffer = Converter.wcsToMbcs (null, string, true);
1364  }
1365  if (tooltipsHandle == 0) {
1366    tooltipsHandle = OS.gtk_tooltips_new ();
1367    if (tooltipsHandle == 0) error (SWT.ERROR_NO_HANDLES);
1368    OS.g_object_ref (tooltipsHandle);
1369    OS.gtk_object_sink (tooltipsHandle);
1370  }
1371  OS.gtk_tooltips_set_tip (tooltipsHandle, widget, buffer, null);
1372}
1373}