KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > widgets > Display


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-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.internal.*;
15 import org.eclipse.swt.internal.win32.*;
16 import org.eclipse.swt.*;
17 import org.eclipse.swt.graphics.*;
18
19 /**
20  * Instances of this class are responsible for managing the
21  * connection between SWT and the underlying operating
22  * system. Their most important function is to implement
23  * the SWT event loop in terms of the platform event model.
24  * They also provide various methods for accessing information
25  * about the operating system, and have overall control over
26  * the operating system resources which SWT allocates.
27  * <p>
28  * Applications which are built with SWT will <em>almost always</em>
29  * require only a single display. In particular, some platforms
30  * which SWT supports will not allow more than one <em>active</em>
31  * display. In other words, some platforms do not support
32  * creating a new display if one already exists that has not been
33  * sent the <code>dispose()</code> message.
34  * <p>
35  * In SWT, the thread which creates a <code>Display</code>
36  * instance is distinguished as the <em>user-interface thread</em>
37  * for that display.
38  * </p>
39  * The user-interface thread for a particular display has the
40  * following special attributes:
41  * <ul>
42  * <li>
43  * The event loop for that display must be run from the thread.
44  * </li>
45  * <li>
46  * Some SWT API methods (notably, most of the public methods in
47  * <code>Widget</code> and its subclasses), may only be called
48  * from the thread. (To support multi-threaded user-interface
49  * applications, class <code>Display</code> provides inter-thread
50  * communication methods which allow threads other than the
51  * user-interface thread to request that it perform operations
52  * on their behalf.)
53  * </li>
54  * <li>
55  * The thread is not allowed to construct other
56  * <code>Display</code>s until that display has been disposed.
57  * (Note that, this is in addition to the restriction mentioned
58  * above concerning platform support for multiple displays. Thus,
59  * the only way to have multiple simultaneously active displays,
60  * even on platforms which support it, is to have multiple threads.)
61  * </li>
62  * </ul>
63  * Enforcing these attributes allows SWT to be implemented directly
64  * on the underlying operating system's event model. This has
65  * numerous benefits including smaller footprint, better use of
66  * resources, safer memory management, clearer program logic,
67  * better performance, and fewer overall operating system threads
68  * required. The down side however, is that care must be taken
69  * (only) when constructing multi-threaded applications to use the
70  * inter-thread communication mechanisms which this class provides
71  * when required.
72  * </p><p>
73  * All SWT API methods which may only be called from the user-interface
74  * thread are distinguished in their documentation by indicating that
75  * they throw the "<code>ERROR_THREAD_INVALID_ACCESS</code>"
76  * SWT exception.
77  * </p>
78  * <dl>
79  * <dt><b>Styles:</b></dt>
80  * <dd>(none)</dd>
81  * <dt><b>Events:</b></dt>
82  * <dd>Close, Dispose, Settings</dd>
83  * </dl>
84  * <p>
85  * IMPORTANT: This class is <em>not</em> intended to be subclassed.
86  * </p>
87  * @see #syncExec
88  * @see #asyncExec
89  * @see #wake
90  * @see #readAndDispatch
91  * @see #sleep
92  * @see Device#dispose
93  */

94
95 public class Display extends Device {
96
97     /**
98      * the handle to the OS message queue
99      * (Warning: This field is platform dependent)
100      * <p>
101      * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
102      * public API. It is marked public only so that it can be shared
103      * within the packages provided by SWT. It is not available on all
104      * platforms and should never be accessed from application code.
105      * </p>
106      */

107     public MSG msg = new MSG ();
108     
109     /* Windows and Events */
110     Event [] eventQueue;
111     Callback windowCallback;
112     int windowProc, threadId;
113     TCHAR windowClass, windowShadowClass;
114     static int WindowClassCount;
115     static final String JavaDoc WindowName = "SWT_Window"; //$NON-NLS-1$
116
static final String JavaDoc WindowShadowName = "SWT_WindowShadow"; //$NON-NLS-1$
117
EventTable eventTable, filterTable;
118
119     /* Widget Table */
120     int [] indexTable;
121     Control lastControl, lastGetControl;
122     int freeSlot, lastHwnd, lastGetHwnd;
123     Control [] controlTable;
124     static final int GROW_SIZE = 1024;
125     static final int SWT_OBJECT_INDEX;
126     static final boolean USE_PROPERTY = !OS.IsWinCE;
127     static {
128         if (USE_PROPERTY) {
129             SWT_OBJECT_INDEX = OS.GlobalAddAtom (new TCHAR (0, "SWT_OBJECT_INDEX", true)); //$NON-NLS-1$
130
} else {
131             SWT_OBJECT_INDEX = 0;
132         }
133     }
134     
135     /* Startup info */
136     static STARTUPINFO lpStartupInfo;
137     static {
138         if (!OS.IsWinCE) {
139             lpStartupInfo = new STARTUPINFO ();
140             lpStartupInfo.cb = STARTUPINFO.sizeof;
141             OS.GetStartupInfo (lpStartupInfo);
142         }
143     }
144     
145     /* XP Themes */
146     int hButtonTheme, hEditTheme, hExplorerBarTheme, hScrollBarTheme, hTabTheme;
147     static final char [] BUTTON = new char [] {'B', 'U', 'T', 'T', 'O', 'N', 0};
148     static final char [] EDIT = new char [] {'E', 'D', 'I', 'T', 0};
149     static final char [] EXPLORER = new char [] {'E', 'X', 'P', 'L', 'O', 'R', 'E', 'R', 0};
150     static final char [] EXPLORERBAR = new char [] {'E', 'X', 'P', 'L', 'O', 'R', 'E', 'R', 'B', 'A', 'R', 0};
151     static final char [] SCROLLBAR = new char [] {'S', 'C', 'R', 'O', 'L', 'L', 'B', 'A', 'R', 0};
152     static final char [] LISTVIEW = new char [] {'L', 'I', 'S', 'T', 'V', 'I', 'E', 'W', 0};
153     static final char [] TAB = new char [] {'T', 'A', 'B', 0};
154     static final char [] TREEVIEW = new char [] {'T', 'R', 'E', 'E', 'V', 'I', 'E', 'W', 0};
155     
156     /* Focus */
157     int focusEvent;
158     Control focusControl;
159     
160     /* Menus */
161     Menu [] bars, popups;
162     MenuItem [] items;
163     
164     /*
165     * The start value for WM_COMMAND id's.
166     * Windows reserves the values 0..100.
167     *
168     * The SmartPhone SWT resource file reserves
169     * the values 101..107.
170     */

171     static final int ID_START = 108;
172     
173     /* Filter Hook */
174     Callback msgFilterCallback;
175     int msgFilterProc, filterHook;
176     MSG hookMsg = new MSG ();
177     boolean runDragDrop = true;
178     
179     /* Idle Hook */
180     Callback foregroundIdleCallback;
181     int foregroundIdleProc, idleHook;
182     
183     /* Message Hook and Embedding */
184     boolean ignoreNextKey;
185     Callback getMsgCallback, embeddedCallback;
186     int getMsgProc, msgHook, embeddedHwnd, embeddedProc;
187     static final String JavaDoc AWT_WINDOW_CLASS = "SunAwtWindow";
188     static final short [] ACCENTS = new short [] {'~', '`', '\'', '^', '"'};
189
190     /* Sync/Async Widget Communication */
191     Synchronizer synchronizer = new Synchronizer (this);
192     boolean runMessages = true, runMessagesInIdle = false;
193     static final String JavaDoc RUN_MESSAGES_IN_IDLE_KEY = "org.eclipse.swt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$
194
Thread JavaDoc thread;
195
196     /* Display Shutdown */
197     Runnable JavaDoc [] disposeList;
198     
199     /* System Tray */
200     Tray tray;
201     int nextTrayId;
202     
203     /* Timers */
204     int [] timerIds;
205     Runnable JavaDoc [] timerList;
206     int nextTimerId = SETTINGS_ID + 1;
207     static final int SETTINGS_ID = 100;
208     static final int SETTINGS_DELAY = 2000;
209     
210     /* Keyboard and Mouse */
211     RECT clickRect;
212     int clickCount, lastTime, lastButton, lastClickHwnd;
213     int lastKey, lastAscii, lastMouse;
214     boolean lastVirtual, lastNull, lastDead;
215     byte [] keyboard = new byte [256];
216     boolean accelKeyHit, mnemonicKeyHit;
217     boolean lockActiveWindow, captureChanged, xMouse;
218     
219     /* Tool Tips */
220     int nextToolTipId;
221     
222     /* MDI */
223     boolean ignoreRestoreFocus;
224     Control lastHittestControl;
225     int lastHittest;
226     
227     /* Message Only Window */
228     Callback messageCallback;
229     int hwndMessage, messageProc;
230     
231     /* System Resources */
232     LOGFONT lfSystemFont;
233     Font systemFont;
234     Image errorImage, infoImage, questionImage, warningIcon;
235     Cursor [] cursors = new Cursor [SWT.CURSOR_HAND + 1];
236     Resource [] resources;
237     static final int RESOURCE_SIZE = 1 + 4 + SWT.CURSOR_HAND + 1;
238
239     /* ImageList Cache */
240     ImageList[] imageList, toolImageList, toolHotImageList, toolDisabledImageList;
241
242     /* Custom Colors for ChooseColor */
243     int lpCustColors;
244
245     /* Sort Indicators */
246     Image upArrow, downArrow;
247     
248     /* Table */
249     char [] tableBuffer;
250     
251     /* Display Data */
252     Object JavaDoc data;
253     String JavaDoc [] keys;
254     Object JavaDoc [] values;
255     
256     /* Key Mappings */
257     static final int [] [] KeyTable = {
258         
259         /* Keyboard and Mouse Masks */
260         {OS.VK_MENU, SWT.ALT},
261         {OS.VK_SHIFT, SWT.SHIFT},
262         {OS.VK_CONTROL, SWT.CONTROL},
263 // {OS.VK_????, SWT.COMMAND},
264

265         /* NOT CURRENTLY USED */
266 // {OS.VK_LBUTTON, SWT.BUTTON1},
267
// {OS.VK_MBUTTON, SWT.BUTTON3},
268
// {OS.VK_RBUTTON, SWT.BUTTON2},
269

270         /* Non-Numeric Keypad Keys */
271         {OS.VK_UP, SWT.ARROW_UP},
272         {OS.VK_DOWN, SWT.ARROW_DOWN},
273         {OS.VK_LEFT, SWT.ARROW_LEFT},
274         {OS.VK_RIGHT, SWT.ARROW_RIGHT},
275         {OS.VK_PRIOR, SWT.PAGE_UP},
276         {OS.VK_NEXT, SWT.PAGE_DOWN},
277         {OS.VK_HOME, SWT.HOME},
278         {OS.VK_END, SWT.END},
279         {OS.VK_INSERT, SWT.INSERT},
280
281         /* Virtual and Ascii Keys */
282         {OS.VK_BACK, SWT.BS},
283         {OS.VK_RETURN, SWT.CR},
284         {OS.VK_DELETE, SWT.DEL},
285         {OS.VK_ESCAPE, SWT.ESC},
286         {OS.VK_RETURN, SWT.LF},
287         {OS.VK_TAB, SWT.TAB},
288     
289         /* Functions Keys */
290         {OS.VK_F1, SWT.F1},
291         {OS.VK_F2, SWT.F2},
292         {OS.VK_F3, SWT.F3},
293         {OS.VK_F4, SWT.F4},
294         {OS.VK_F5, SWT.F5},
295         {OS.VK_F6, SWT.F6},
296         {OS.VK_F7, SWT.F7},
297         {OS.VK_F8, SWT.F8},
298         {OS.VK_F9, SWT.F9},
299         {OS.VK_F10, SWT.F10},
300         {OS.VK_F11, SWT.F11},
301         {OS.VK_F12, SWT.F12},
302         {OS.VK_F13, SWT.F13},
303         {OS.VK_F14, SWT.F14},
304         {OS.VK_F15, SWT.F15},
305         
306         /* Numeric Keypad Keys */
307         {OS.VK_MULTIPLY, SWT.KEYPAD_MULTIPLY},
308         {OS.VK_ADD, SWT.KEYPAD_ADD},
309         {OS.VK_RETURN, SWT.KEYPAD_CR},
310         {OS.VK_SUBTRACT, SWT.KEYPAD_SUBTRACT},
311         {OS.VK_DECIMAL, SWT.KEYPAD_DECIMAL},
312         {OS.VK_DIVIDE, SWT.KEYPAD_DIVIDE},
313         {OS.VK_NUMPAD0, SWT.KEYPAD_0},
314         {OS.VK_NUMPAD1, SWT.KEYPAD_1},
315         {OS.VK_NUMPAD2, SWT.KEYPAD_2},
316         {OS.VK_NUMPAD3, SWT.KEYPAD_3},
317         {OS.VK_NUMPAD4, SWT.KEYPAD_4},
318         {OS.VK_NUMPAD5, SWT.KEYPAD_5},
319         {OS.VK_NUMPAD6, SWT.KEYPAD_6},
320         {OS.VK_NUMPAD7, SWT.KEYPAD_7},
321         {OS.VK_NUMPAD8, SWT.KEYPAD_8},
322         {OS.VK_NUMPAD9, SWT.KEYPAD_9},
323 // {OS.VK_????, SWT.KEYPAD_EQUAL},
324

325         /* Other keys */
326         {OS.VK_CAPITAL, SWT.CAPS_LOCK},
327         {OS.VK_NUMLOCK, SWT.NUM_LOCK},
328         {OS.VK_SCROLL, SWT.SCROLL_LOCK},
329         {OS.VK_PAUSE, SWT.PAUSE},
330         {OS.VK_CANCEL, SWT.BREAK},
331         {OS.VK_SNAPSHOT, SWT.PRINT_SCREEN},
332 // {OS.VK_????, SWT.HELP},
333

334     };
335
336     /* Multiple Displays */
337     static Display Default;
338     static Display [] Displays = new Display [4];
339
340     /* Multiple Monitors */
341     Monitor[] monitors = null;
342     int monitorCount = 0;
343     
344     /* Modality */
345     Shell [] modalShells;
346     Shell modalDialogShell;
347     static boolean TrimEnabled = false;
348
349     /* Private SWT Window Messages */
350     static final int SWT_GETACCELCOUNT = OS.WM_APP;
351     static final int SWT_GETACCEL = OS.WM_APP + 1;
352     static final int SWT_KEYMSG = OS.WM_APP + 2;
353     static final int SWT_DESTROY = OS.WM_APP + 3;
354     static final int SWT_TRAYICONMSG = OS.WM_APP + 4;
355     static final int SWT_NULL = OS.WM_APP + 5;
356     static final int SWT_RUNASYNC = OS.WM_APP + 6;
357     static int SWT_TASKBARCREATED;
358     static int SWT_RESTORECARET;
359     
360     /* Workaround for Adobe Reader 7.0 */
361     int hitCount;
362     
363     /* Package Name */
364     static final String JavaDoc PACKAGE_PREFIX = "org.eclipse.swt.widgets."; //$NON-NLS-1$
365
/*
366     * This code is intentionally commented. In order
367     * to support CLDC, .class cannot be used because
368     * it does not compile on some Java compilers when
369     * they are targeted for CLDC.
370     */

371 // static {
372
// String name = Display.class.getName ();
373
// int index = name.lastIndexOf ('.');
374
// PACKAGE_PREFIX = name.substring (0, index + 1);
375
// }
376

377     /*
378     * TEMPORARY CODE. Install the runnable that
379     * gets the current display. This code will
380     * be removed in the future.
381     */

382     static {
383         DeviceFinder = new Runnable JavaDoc () {
384             public void run () {
385                 Device device = getCurrent ();
386                 if (device == null) {
387                     device = getDefault ();
388                 }
389                 setDevice (device);
390             }
391         };
392     }
393
394 /*
395 * TEMPORARY CODE.
396 */

397 static void setDevice (Device device) {
398     CurrentDevice = device;
399 }
400     
401 /**
402  * Constructs a new instance of this class.
403  * <p>
404  * Note: The resulting display is marked as the <em>current</em>
405  * display. If this is the first display which has been
406  * constructed since the application started, it is also
407  * marked as the <em>default</em> display.
408  * </p>
409  *
410  * @exception SWTException <ul>
411  * <li>ERROR_THREAD_INVALID_ACCESS - if called from a thread that already created an existing display</li>
412  * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
413  * </ul>
414  *
415  * @see #getCurrent
416  * @see #getDefault
417  * @see Widget#checkSubclass
418  * @see Shell
419  */

420 public Display () {
421     this (null);
422 }
423
424 /**
425  * Constructs a new instance of this class using the parameter.
426  *
427  * @param data the device data
428  */

429 public Display (DeviceData data) {
430     super (data);
431 }
432
433 Control _getFocusControl () {
434     return findControl (OS.GetFocus ());
435 }
436
437 void addBar (Menu menu) {
438     if (bars == null) bars = new Menu [4];
439     int length = bars.length;
440     for (int i=0; i<length; i++) {
441         if (bars [i] == menu) return;
442     }
443     int index = 0;
444     while (index < length) {
445         if (bars [index] == null) break;
446         index++;
447     }
448     if (index == length) {
449         Menu [] newBars = new Menu [length + 4];
450         System.arraycopy (bars, 0, newBars, 0, length);
451         bars = newBars;
452     }
453     bars [index] = menu;
454 }
455
456 void addControl (int handle, Control control) {
457     if (handle == 0) return;
458     if (freeSlot == -1) {
459         int length = (freeSlot = indexTable.length) + GROW_SIZE;
460         int [] newIndexTable = new int [length];
461         Control [] newControlTable = new Control [length];
462         System.arraycopy (indexTable, 0, newIndexTable, 0, freeSlot);
463         System.arraycopy (controlTable, 0, newControlTable, 0, freeSlot);
464         for (int i=freeSlot; i<length-1; i++) newIndexTable [i] = i + 1;
465         newIndexTable [length - 1] = -1;
466         indexTable = newIndexTable;
467         controlTable = newControlTable;
468     }
469     if (USE_PROPERTY) {
470         OS.SetProp (handle, SWT_OBJECT_INDEX, freeSlot + 1);
471     } else {
472         OS.SetWindowLong (handle, OS.GWL_USERDATA, freeSlot + 1);
473     }
474     int oldSlot = freeSlot;
475     freeSlot = indexTable [oldSlot];
476     indexTable [oldSlot] = -2;
477     controlTable [oldSlot] = control;
478 }
479
480 /**
481  * Adds the listener to the collection of listeners who will
482  * be notified when an event of the given type occurs anywhere
483  * in a widget. The event type is one of the event constants
484  * defined in class <code>SWT</code>. When the event does occur,
485  * the listener is notified by sending it the <code>handleEvent()</code>
486  * message.
487  * <p>
488  * Setting the type of an event to <code>SWT.None</code> from
489  * within the <code>handleEvent()</code> method can be used to
490  * change the event type and stop subsequent Java listeners
491  * from running. Because event filters run before other listeners,
492  * event filters can both block other listeners and set arbitrary
493  * fields within an event. For this reason, event filters are both
494  * powerful and dangerous. They should generally be avoided for
495  * performance, debugging and code maintenance reasons.
496  * </p>
497  *
498  * @param eventType the type of event to listen for
499  * @param listener the listener which should be notified when the event occurs
500  *
501  * @exception IllegalArgumentException <ul>
502  * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
503  * </ul>
504  * @exception SWTException <ul>
505  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
506  * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
507  * </ul>
508  *
509  * @see Listener
510  * @see SWT
511  * @see #removeFilter
512  * @see #removeListener
513  *
514  * @since 3.0
515  */

516 public void addFilter (int eventType, Listener listener) {
517     checkDevice ();
518     if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
519     if (filterTable == null) filterTable = new EventTable ();
520     filterTable.hook (eventType, listener);
521 }
522
523 /**
524  * Adds the listener to the collection of listeners who will
525  * be notified when an event of the given type occurs. The event
526  * type is one of the event constants defined in class <code>SWT</code>.
527  * When the event does occur in the display, the listener is notified by
528  * sending it the <code>handleEvent()</code> message.
529  *
530  * @param eventType the type of event to listen for
531  * @param listener the listener which should be notified when the event occurs
532  *
533  * @exception IllegalArgumentException <ul>
534  * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
535  * </ul>
536  * @exception SWTException <ul>
537  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
538  * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
539  * </ul>
540  *
541  * @see Listener
542  * @see SWT
543  * @see #removeListener
544  *
545  * @since 2.0
546  */

547 public void addListener (int eventType, Listener listener) {
548     checkDevice ();
549     if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
550     if (eventTable == null) eventTable = new EventTable ();
551     eventTable.hook (eventType, listener);
552 }
553
554 void addMenuItem (MenuItem item) {
555     if (items == null) items = new MenuItem [64];
556     for (int i=0; i<items.length; i++) {
557         if (items [i] == null) {
558             item.id = i + ID_START;
559             items [i] = item;
560             return;
561         }
562     }
563     item.id = items.length + ID_START;
564     MenuItem [] newItems = new MenuItem [items.length + 64];
565     newItems [items.length] = item;
566     System.arraycopy (items, 0, newItems, 0, items.length);
567     items = newItems;
568 }
569
570 void addPopup (Menu menu) {
571     if (popups == null) popups = new Menu [4];
572     int length = popups.length;
573     for (int i=0; i<length; i++) {
574         if (popups [i] == menu) return;
575     }
576     int index = 0;
577     while (index < length) {
578         if (popups [index] == null) break;
579         index++;
580     }
581     if (index == length) {
582         Menu [] newPopups = new Menu [length + 4];
583         System.arraycopy (popups, 0, newPopups, 0, length);
584         popups = newPopups;
585     }
586     popups [index] = menu;
587 }
588
589 int asciiKey (int key) {
590     if (OS.IsWinCE) return 0;
591     
592     /* Get the current keyboard. */
593     for (int i=0; i<keyboard.length; i++) keyboard [i] = 0;
594     if (!OS.GetKeyboardState (keyboard)) return 0;
595         
596     /* Translate the key to ASCII or UNICODE using the virtual keyboard */
597     if (OS.IsUnicode) {
598         char [] result = new char [1];
599         if (OS.ToUnicode (key, key, keyboard, result, 1, 0) == 1) return result [0];
600     } else {
601         short [] result = new short [1];
602         if (OS.ToAscii (key, key, keyboard, result, 0) == 1) return result [0];
603     }
604     return 0;
605 }
606
607 /**
608  * Causes the <code>run()</code> method of the runnable to
609  * be invoked by the user-interface thread at the next
610  * reasonable opportunity. The caller of this method continues
611  * to run in parallel, and is not notified when the
612  * runnable has completed. Specifying <code>null</code> as the
613  * runnable simply wakes the user-interface thread when run.
614  * <p>
615  * Note that at the time the runnable is invoked, widgets
616  * that have the receiver as their display may have been
617  * disposed. Therefore, it is necessary to check for this
618  * case inside the runnable before accessing the widget.
619  * </p>
620  *
621  * @param runnable code to run on the user-interface thread or <code>null</code>
622  *
623  * @exception SWTException <ul>
624  * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
625  * </ul>
626  *
627  * @see #syncExec
628  */

629 public void asyncExec (Runnable JavaDoc runnable) {
630     if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
631     synchronizer.asyncExec (runnable);
632 }
633
634 /**
635  * Causes the system hardware to emit a short sound
636  * (if it supports this capability).
637  *
638  * @exception SWTException <ul>
639  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
640  * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
641  * </ul>
642  */

643 public void beep () {
644     checkDevice ();
645     OS.MessageBeep (OS.MB_OK);
646 }
647
648 /**
649  * Checks that this class can be subclassed.
650  * <p>
651  * IMPORTANT: See the comment in <code>Widget.checkSubclass()</code>.
652  * </p>
653  *
654  * @exception SWTException <ul>
655  * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
656  * </ul>
657  *
658  * @see Widget#checkSubclass
659  */

660 protected void checkSubclass () {
661     if (!isValidClass (getClass ())) error (SWT.ERROR_INVALID_SUBCLASS);
662 }
663
664 protected void checkDevice () {
665     if (thread == null) error (SWT.ERROR_WIDGET_DISPOSED);
666     if (thread != Thread.currentThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
667     if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
668 }
669
670 static synchronized void checkDisplay (Thread JavaDoc thread, boolean multiple) {
671     for (int i=0; i<Displays.length; i++) {
672         if (Displays [i] != null) {
673             if (!multiple) SWT.error (SWT.ERROR_NOT_IMPLEMENTED, null, " [multiple displays]");
674             if (Displays [i].thread == thread) SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS);
675         }
676     }
677 }
678
679 void clearModal (Shell shell) {
680     if (modalShells == null) return;
681     int index = 0, length = modalShells.length;
682     while (index < length) {
683         if (modalShells [index] == shell) break;
684         if (modalShells [index] == null) return;
685         index++;
686     }
687     if (index == length) return;
688     System.arraycopy (modalShells, index + 1, modalShells, index, --length - index);
689     modalShells [length] = null;
690     if (index == 0 && modalShells [0] == null) modalShells = null;
691     Shell [] shells = getShells ();
692     for (int i=0; i<shells.length; i++) shells [i].updateModal ();
693 }
694
695 int controlKey (int key) {
696     int upper = OS.CharUpper ((short) key);
697     if (64 <= upper && upper <= 95) return upper & 0xBF;
698     return key;
699 }
700
701 /**
702  * Requests that the connection between SWT and the underlying
703  * operating system be closed.
704  *
705  * @exception SWTException <ul>
706  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
707  * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
708  * </ul>
709  *
710  * @see Device#dispose
711  *
712  * @since 2.0
713  */

714 public void close () {
715     checkDevice ();
716     Event event = new Event ();
717     sendEvent (SWT.Close, event);
718     if (event.doit) dispose ();
719 }
720
721 /**
722  * Creates the device in the operating system. If the device
723  * does not have a handle, this method may do nothing depending
724  * on the device.
725  * <p>
726  * This method is called before <code>init</code>.
727  * </p>
728  *
729  * @param data the DeviceData which describes the receiver
730  *
731  * @see #init
732  */

733 protected void create (DeviceData data) {
734     checkSubclass ();
735     checkDisplay (thread = Thread.currentThread (), true);
736     createDisplay (data);
737     register (this);
738     if (Default == null) Default = this;
739 }
740
741 void createDisplay (DeviceData data) {
742 }
743
744 static int create32bitDIB (Image image) {
745     int transparentPixel = -1, alpha = -1, hMask = 0, hBitmap = 0;
746     byte[] alphaData = null;
747     switch (image.type) {
748         case SWT.ICON:
749             ICONINFO info = new ICONINFO ();
750             OS.GetIconInfo (image.handle, info);
751             hBitmap = info.hbmColor;
752             hMask = info.hbmMask;
753             break;
754         case SWT.BITMAP:
755             ImageData data = image.getImageData ();
756             hBitmap = image.handle;
757             alpha = data.alpha;
758             alphaData = data.alphaData;
759             transparentPixel = data.transparentPixel;
760             break;
761     }
762     BITMAP bm = new BITMAP ();
763     OS.GetObject (hBitmap, BITMAP.sizeof, bm);
764     int imgWidth = bm.bmWidth;
765     int imgHeight = bm.bmHeight;
766     int hDC = OS.GetDC (0);
767     int srcHdc = OS.CreateCompatibleDC (hDC);
768     int oldSrcBitmap = OS.SelectObject (srcHdc, hBitmap);
769     int memHdc = OS.CreateCompatibleDC (hDC);
770     BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER ();
771     bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
772     bmiHeader.biWidth = imgWidth;
773     bmiHeader.biHeight = -imgHeight;
774     bmiHeader.biPlanes = 1;
775     bmiHeader.biBitCount = (short)32;
776     bmiHeader.biCompression = OS.BI_RGB;
777     byte [] bmi = new byte [BITMAPINFOHEADER.sizeof];
778     OS.MoveMemory (bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
779     int [] pBits = new int [1];
780     int memDib = OS.CreateDIBSection (0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
781     if (memDib == 0) SWT.error (SWT.ERROR_NO_HANDLES);
782     int oldMemBitmap = OS.SelectObject (memHdc, memDib);
783     BITMAP dibBM = new BITMAP ();
784     OS.GetObject (memDib, BITMAP.sizeof, dibBM);
785     int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight;
786     OS.BitBlt (memHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, 0, OS.SRCCOPY);
787     byte red = 0, green = 0, blue = 0;
788     if (transparentPixel != -1) {
789         if (bm.bmBitsPixel <= 8) {
790             byte [] color = new byte [4];
791             OS.GetDIBColorTable (srcHdc, transparentPixel, 1, color);
792             blue = color [0];
793             green = color [1];
794             red = color [2];
795         } else {
796             switch (bm.bmBitsPixel) {
797                 case 16:
798                     blue = (byte)((transparentPixel & 0x1F) << 3);
799                     green = (byte)((transparentPixel & 0x3E0) >> 2);
800                     red = (byte)((transparentPixel & 0x7C00) >> 7);
801                     break;
802                 case 24:
803                     blue = (byte)((transparentPixel & 0xFF0000) >> 16);
804                     green = (byte)((transparentPixel & 0xFF00) >> 8);
805                     red = (byte)(transparentPixel & 0xFF);
806                     break;
807                 case 32:
808                     blue = (byte)((transparentPixel & 0xFF000000) >>> 24);
809                     green = (byte)((transparentPixel & 0xFF0000) >> 16);
810                     red = (byte)((transparentPixel & 0xFF00) >> 8);
811                     break;
812             }
813         }
814     }
815     byte [] srcData = new byte [sizeInBytes];
816     OS.MoveMemory (srcData, pBits [0], sizeInBytes);
817     if (hMask != 0) {
818         OS.SelectObject(srcHdc, hMask);
819         for (int y = 0, dp = 0; y < imgHeight; ++y) {
820             for (int x = 0; x < imgWidth; ++x) {
821                 if (OS.GetPixel(srcHdc, x, y) != 0) {
822                     srcData [dp + 0] = srcData [dp + 1] = srcData [dp + 2] = srcData[dp + 3] = (byte)0;
823                 } else {
824                     srcData[dp + 3] = (byte)0xFF;
825                 }
826                 dp += 4;
827             }
828         }
829     } else if (alpha != -1) {
830         for (int y = 0, dp = 0; y < imgHeight; ++y) {
831             for (int x = 0; x < imgWidth; ++x) {
832                 srcData [dp + 3] = (byte)alpha;
833                 if (srcData [dp + 3] == 0) srcData [dp + 0] = srcData [dp + 1] = srcData [dp + 2] = 0;
834                 dp += 4;
835             }
836         }
837     } else if (alphaData != null) {
838         for (int y = 0, dp = 0, ap = 0; y < imgHeight; ++y) {
839             for (int x = 0; x < imgWidth; ++x) {
840                 srcData [dp + 3] = alphaData [ap++];
841                 if (srcData [dp + 3] == 0) srcData [dp + 0] = srcData [dp + 1] = srcData [dp + 2] = 0;
842                 dp += 4;
843             }
844         }
845     } else if (transparentPixel != -1) {
846         for (int y = 0, dp = 0; y < imgHeight; ++y) {
847             for (int x = 0; x < imgWidth; ++x) {
848                 if (srcData [dp] == blue && srcData [dp + 1] == green && srcData [dp + 2] == red) {
849                     srcData [dp + 0] = srcData [dp + 1] = srcData [dp + 2] = srcData [dp + 3] = (byte)0;
850                 } else {
851                     srcData [dp + 3] = (byte)0xFF;
852                 }
853                 dp += 4;
854             }
855         }
856     } else {
857         for (int y = 0, dp = 0; y < imgHeight; ++y) {
858             for (int x = 0; x < imgWidth; ++x) {
859                 srcData [dp + 3] = (byte)0xFF;
860                 dp += 4;
861             }
862         }
863     }
864     OS.MoveMemory (pBits [0], srcData, sizeInBytes);
865     OS.SelectObject (srcHdc, oldSrcBitmap);
866     OS.SelectObject (memHdc, oldMemBitmap);
867     OS.DeleteObject (srcHdc);
868     OS.DeleteObject (memHdc);
869     OS.ReleaseDC (0, hDC);
870     if (hBitmap != image.handle && hBitmap != 0) OS.DeleteObject (hBitmap);
871     if (hMask != 0) OS.DeleteObject (hMask);
872     return memDib;
873 }
874
875 static int create32bitDIB (int hBitmap, int alpha, byte [] alphaData, int transparentPixel) {
876     BITMAP bm = new BITMAP ();
877     OS.GetObject (hBitmap, BITMAP.sizeof, bm);
878     int imgWidth = bm.bmWidth;
879     int imgHeight = bm.bmHeight;
880     int hDC = OS.GetDC (0);
881     int srcHdc = OS.CreateCompatibleDC (hDC);
882     int oldSrcBitmap = OS.SelectObject (srcHdc, hBitmap);
883     int memHdc = OS.CreateCompatibleDC (hDC);
884     BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER ();
885     bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
886     bmiHeader.biWidth = imgWidth;
887     bmiHeader.biHeight = -imgHeight;
888     bmiHeader.biPlanes = 1;
889     bmiHeader.biBitCount = (short)32;
890     bmiHeader.biCompression = OS.BI_RGB;
891     byte [] bmi = new byte [BITMAPINFOHEADER.sizeof];
892     OS.MoveMemory (bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
893     int [] pBits = new int [1];
894     int memDib = OS.CreateDIBSection (0, bmi, OS.DIB_RGB_COLORS, pBits, 0, 0);
895     if (memDib == 0) SWT.error (SWT.ERROR_NO_HANDLES);
896     int oldMemBitmap = OS.SelectObject (memHdc, memDib);
897     BITMAP dibBM = new BITMAP ();
898     OS.GetObject (memDib, BITMAP.sizeof, dibBM);
899     int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight;
900     OS.BitBlt (memHdc, 0, 0, imgWidth, imgHeight, srcHdc, 0, 0, OS.SRCCOPY);
901     byte red = 0, green = 0, blue = 0;
902     if (transparentPixel != -1) {
903         if (bm.bmBitsPixel <= 8) {
904             byte [] color = new byte [4];
905             OS.GetDIBColorTable (srcHdc, transparentPixel, 1, color);
906             blue = color [0];
907             green = color [1];
908             red = color [2];
909         } else {
910             switch (bm.bmBitsPixel) {
911                 case 16:
912                     blue = (byte)((transparentPixel & 0x1F) << 3);
913                     green = (byte)((transparentPixel & 0x3E0) >> 2);
914                     red = (byte)((transparentPixel & 0x7C00) >> 7);
915                     break;
916                 case 24:
917                     blue = (byte)((transparentPixel & 0xFF0000) >> 16);
918                     green = (byte)((transparentPixel & 0xFF00) >> 8);
919                     red = (byte)(transparentPixel & 0xFF);
920                     break;
921                 case 32:
922                     blue = (byte)((transparentPixel & 0xFF000000) >>> 24);
923                     green = (byte)((transparentPixel & 0xFF0000) >> 16);
924                     red = (byte)((transparentPixel & 0xFF00) >> 8);
925                     break;
926             }
927         }
928     }
929     OS.SelectObject (srcHdc, oldSrcBitmap);
930     OS.SelectObject (memHdc, oldMemBitmap);
931     OS.DeleteObject (srcHdc);
932     OS.DeleteObject (memHdc);
933     OS.ReleaseDC (0, hDC);
934     byte [] srcData = new byte [sizeInBytes];
935     OS.MoveMemory (srcData, pBits [0], sizeInBytes);
936     if (alpha != -1) {
937