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

Quick Search    Search Deep

Source code: org/eclipse/swt/widgets/Display.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  
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</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  public class Display extends Device {
95  
96    /* Events Dispatching and Callback */
97    boolean wake;
98    int gdkEventCount;
99    long /*int*/ [] gdkEvents;
100   int [] dispatchEvents;
101   Widget [] gdkEventWidgets;
102   Event [] eventQueue;
103   Callback eventCallback, filterCallback;
104   GdkEventButton gdkEvent = new GdkEventButton ();
105   long /*int*/ eventProc, filterProc, windowProc2, windowProc3, windowProc4, windowProc5;
106   Callback windowCallback2, windowCallback3, windowCallback4, windowCallback5;
107   EventTable eventTable, filterTable;
108   static String APP_NAME = "SWT";
109   static final String DISPATCH_EVENT_KEY = "org.eclipse.swt.internal.gtk.dispatchEvent";
110 
111   /* Widget Table */
112   int freeSlot;
113   int [] indexTable;
114   Widget [] widgetTable;
115   final static int GROW_SIZE = 1024;
116   static final int SWT_OBJECT_INDEX;
117   static {
118     byte [] buffer = Converter.wcsToMbcs (null, "SWT_OBJECT_INDEX", true);
119     SWT_OBJECT_INDEX = OS.g_quark_from_string (buffer);
120   }
121     
122   /* Input method resources */
123   Control imControl;
124   long /*int*/ preeditWindow, preeditLabel;
125 
126   /* Sync/Async Widget Communication */
127   Synchronizer synchronizer = new Synchronizer (this);
128   Thread thread;
129 
130   /* Display Shutdown */
131   Runnable [] disposeList;
132   
133   /* System Tray */
134   Tray tray;
135   
136   /* Timers */
137   int [] timerIds;
138   Runnable [] timerList;
139   Callback timerCallback;
140   long /*int*/ timerProc;
141   Callback windowTimerCallback;
142   long /*int*/ windowTimerProc;
143   
144   /* Caret */
145   Caret currentCaret;
146   Callback caretCallback;
147   int caretId;
148   long /*int*/ caretProc;
149   
150   /* Mnemonics */
151   Control mnemonicControl;
152 
153   /* Mouse hover */
154   int mouseHoverId;
155   long /*int*/ mouseHoverHandle, mouseHoverProc;
156   Callback mouseHoverCallback;
157   
158   /* Menu position callback */
159   long /*int*/ menuPositionProc;
160   Callback menuPositionCallback;
161 
162   /* Shell map callback */
163   long /*int*/ shellMapProc;
164   Callback shellMapCallback;
165   
166   /* GtkTreeView callbacks */
167   int[] treeSelection;
168   int treeSelectionLength;
169   long /*int*/ treeSelectionProc;
170   Callback treeSelectionCallback;
171   long /*int*/ textCellDataProc;
172   Callback textCellDataCallback;
173   long /*int*/ pixbufCellDataProc;
174   Callback pixbufCellDataCallback;
175   
176   /* Flush exposes */
177   long /*int*/ checkIfEventProc;
178   Callback checkIfEventCallback;
179   long /*int*/ flushWindow;
180   boolean flushAll;
181   GdkRectangle flushRect = new GdkRectangle ();
182   XExposeEvent exposeEvent = new XExposeEvent ();
183   XVisibilityEvent visibilityEvent = new XVisibilityEvent ();
184   long /*int*/ [] flushData = new long /*int*/ [1];
185 
186   /* Drag Detect */
187   int dragStartX,dragStartY;
188   boolean dragging;
189   
190   /* Fonts */
191   long /*int*/ defaultFont;
192 
193   /* System Images */
194   long /*int*/ errorPixmap, infoPixmap, questionPixmap, warningPixmap;
195   long /*int*/ errorMask, infoMask, questionMask, warningMask;
196   
197   /* System Cursors */
198   Cursor [] cursors = new Cursor [SWT.CURSOR_HAND + 1];
199 
200   /* Colors */
201   GdkColor COLOR_WIDGET_DARK_SHADOW, COLOR_WIDGET_NORMAL_SHADOW, COLOR_WIDGET_LIGHT_SHADOW;
202   GdkColor COLOR_WIDGET_HIGHLIGHT_SHADOW, COLOR_WIDGET_BACKGROUND, COLOR_WIDGET_FOREGROUND, COLOR_WIDGET_BORDER;
203   GdkColor COLOR_LIST_FOREGROUND, COLOR_LIST_BACKGROUND, COLOR_LIST_SELECTION, COLOR_LIST_SELECTION_TEXT;
204   GdkColor COLOR_TEXT_FOREGROUND, COLOR_TEXT_BACKGROUND, COLOR_INFO_BACKGROUND, COLOR_INFO_FOREGROUND;
205   GdkColor COLOR_TITLE_FOREGROUND, COLOR_TITLE_BACKGROUND, COLOR_TITLE_BACKGROUND_GRADIENT;
206   GdkColor COLOR_TITLE_INACTIVE_FOREGROUND, COLOR_TITLE_INACTIVE_BACKGROUND, COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT;
207 
208   /* Popup Menus */
209   Menu [] popups;
210   int popupTime;
211   
212   /* Key Mappings */
213   static final int [] [] KeyTable = {
214     
215     /* Keyboard and Mouse Masks */
216     {OS.GDK_Alt_L,    SWT.ALT},
217     {OS.GDK_Alt_R,    SWT.ALT},
218     {OS.GDK_Meta_L,  SWT.ALT},
219     {OS.GDK_Meta_R,  SWT.ALT},
220     {OS.GDK_Shift_L,    SWT.SHIFT},
221     {OS.GDK_Shift_R,    SWT.SHIFT},
222     {OS.GDK_Control_L,  SWT.CONTROL},
223     {OS.GDK_Control_R,  SWT.CONTROL},
224 //    {OS.GDK_????,    SWT.COMMAND},
225 //    {OS.GDK_????,    SWT.COMMAND},
226     
227     /* Non-Numeric Keypad Keys */
228     {OS.GDK_Up,            SWT.ARROW_UP},
229     {OS.GDK_KP_Up,          SWT.ARROW_UP},
230     {OS.GDK_Down,          SWT.ARROW_DOWN},
231     {OS.GDK_KP_Down,      SWT.ARROW_DOWN},
232     {OS.GDK_Left,            SWT.ARROW_LEFT},
233     {OS.GDK_KP_Left,        SWT.ARROW_LEFT},
234     {OS.GDK_Right,          SWT.ARROW_RIGHT},
235     {OS.GDK_KP_Right,        SWT.ARROW_RIGHT},
236     {OS.GDK_Page_Up,        SWT.PAGE_UP},
237     {OS.GDK_KP_Page_Up,    SWT.PAGE_UP},
238     {OS.GDK_Page_Down,      SWT.PAGE_DOWN},
239     {OS.GDK_KP_Page_Down,  SWT.PAGE_DOWN},
240     {OS.GDK_Home,          SWT.HOME},
241     {OS.GDK_KP_Home,      SWT.HOME},
242     {OS.GDK_End,            SWT.END},
243     {OS.GDK_KP_End,        SWT.END},
244     {OS.GDK_Insert,          SWT.INSERT},
245     {OS.GDK_KP_Insert,      SWT.INSERT},
246     
247     /* Virtual and Ascii Keys */
248     {OS.GDK_BackSpace,    SWT.BS},
249     {OS.GDK_Return,        SWT.CR},
250     {OS.GDK_Delete,        SWT.DEL},
251     {OS.GDK_KP_Delete,    SWT.DEL},
252     {OS.GDK_Escape,      SWT.ESC},
253     {OS.GDK_Linefeed,      SWT.LF},
254     {OS.GDK_Tab,          SWT.TAB},
255     {OS.GDK_ISO_Left_Tab,   SWT.TAB},
256   
257     /* Functions Keys */
258     {OS.GDK_F1,    SWT.F1},
259     {OS.GDK_F2,    SWT.F2},
260     {OS.GDK_F3,    SWT.F3},
261     {OS.GDK_F4,    SWT.F4},
262     {OS.GDK_F5,    SWT.F5},
263     {OS.GDK_F6,    SWT.F6},
264     {OS.GDK_F7,    SWT.F7},
265     {OS.GDK_F8,    SWT.F8},
266     {OS.GDK_F9,    SWT.F9},
267     {OS.GDK_F10,    SWT.F10},
268     {OS.GDK_F11,    SWT.F11},
269     {OS.GDK_F12,    SWT.F12},
270     {OS.GDK_F13,    SWT.F13},
271     {OS.GDK_F14,    SWT.F14},
272     {OS.GDK_F15,    SWT.F15},
273     
274     /* Numeric Keypad Keys */
275     {OS.GDK_KP_Multiply,    SWT.KEYPAD_MULTIPLY},
276     {OS.GDK_KP_Add,      SWT.KEYPAD_ADD},
277     {OS.GDK_KP_Enter,      SWT.KEYPAD_CR},
278     {OS.GDK_KP_Subtract,  SWT.KEYPAD_SUBTRACT},
279     {OS.GDK_KP_Decimal,  SWT.KEYPAD_DECIMAL},
280     {OS.GDK_KP_Divide,    SWT.KEYPAD_DIVIDE},
281     {OS.GDK_KP_0,      SWT.KEYPAD_0},
282     {OS.GDK_KP_1,      SWT.KEYPAD_1},
283     {OS.GDK_KP_2,      SWT.KEYPAD_2},
284     {OS.GDK_KP_3,      SWT.KEYPAD_3},
285     {OS.GDK_KP_4,      SWT.KEYPAD_4},
286     {OS.GDK_KP_5,      SWT.KEYPAD_5},
287     {OS.GDK_KP_6,      SWT.KEYPAD_6},
288     {OS.GDK_KP_7,      SWT.KEYPAD_7},
289     {OS.GDK_KP_8,      SWT.KEYPAD_8},
290     {OS.GDK_KP_9,      SWT.KEYPAD_9},
291     {OS.GDK_KP_Equal,  SWT.KEYPAD_EQUAL},
292 
293     /* Other keys */
294     {OS.GDK_Caps_Lock,    SWT.CAPS_LOCK},
295     {OS.GDK_Num_Lock,    SWT.NUM_LOCK},
296     {OS.GDK_Scroll_Lock,    SWT.SCROLL_LOCK},
297     {OS.GDK_Pause,        SWT.PAUSE},
298     {OS.GDK_Break,        SWT.BREAK},
299     {OS.GDK_Print,          SWT.PRINT_SCREEN},
300     {OS.GDK_Help,          SWT.HELP},
301     
302   };
303 
304   /* Multiple Displays. */
305   static Display Default;
306   static Display [] Displays = new Display [4];
307 
308   /* Package name */
309   static final String PACKAGE_PREFIX = "org.eclipse.swt.widgets.";
310   /* This code is intentionally commented.
311    * ".class" can not be used on CLDC.
312    */
313   /*static {
314     String name = Display.class.getName ();
315     int index = name.lastIndexOf ('.');
316     PACKAGE_NAME = name.substring (0, index + 1);
317   }*/
318 
319   /*
320   * In order to support CLDC, .class cannot be used because
321   * it does not compile on some Java compilers when they are
322   * targeted for CLDC.  Use Class.forName() instead.
323   */
324   static final Class OS_LOCK;
325   static {
326     Class lock = null;
327     try {
328       lock = Class.forName ("org.eclipse.swt.internal.gtk.OS");
329     } catch (Throwable th) {
330     }
331     OS_LOCK = lock;
332   }
333   
334   /* #define in gdkevents.h */
335   static final int DOUBLE_CLICK_TIME = 250;
336 
337   /* GTK Version */
338   static final int MAJOR = 2;
339   static final int MINOR = 0;
340   static final int MICRO = 6;
341 
342   /* Display Data */
343   Object data;
344   String [] keys;
345   Object [] values;
346   
347   /* Initial Guesses for Shell Trimmings. */
348   int borderTrimWidth = 4, borderTrimHeight = 4;
349   int resizeTrimWidth = 6, resizeTrimHeight = 6;
350   int titleBorderTrimWidth = 5, titleBorderTrimHeight = 28;
351   int titleResizeTrimWidth = 6, titleResizeTrimHeight = 29;
352   int titleTrimWidth = 0, titleTrimHeight = 23;
353   
354   /*
355   * TEMPORARY CODE.  Install the runnable that
356   * gets the current display. This code will
357   * be removed in the future.
358   */
359   static {
360     DeviceFinder = new Runnable () {
361       public void run () {
362         Device device = getCurrent ();
363         if (device == null) {
364           device = getDefault ();
365         }
366         setDevice (device);
367       }
368     };
369   }
370 
371 /*
372 * TEMPORARY CODE.
373 */
374 static void setDevice (Device device) {
375   CurrentDevice = device;
376 }
377 
378 /**
379  * Constructs a new instance of this class.
380  * <p>
381  * Note: The resulting display is marked as the <em>current</em>
382  * display. If this is the first display which has been 
383  * constructed since the application started, it is also
384  * marked as the <em>default</em> display.
385  * </p>
386  *
387  * @exception SWTException <ul>
388  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
389  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
390  * </ul>
391  *
392  * @see #getCurrent
393  * @see #getDefault
394  * @see Widget#checkSubclass
395  * @see Shell
396  */
397 public Display () {
398   this (null);
399 }
400 
401 public Display (DeviceData data) {
402   super (data);
403 }
404 
405 /**
406  * Adds the listener to the collection of listeners who will
407  * be notifed when an event of the given type occurs anywhere
408  * in this display. When the event does occur, the listener is
409  * notified by sending it the <code>handleEvent()</code> message.
410  *
411  * @param eventType the type of event to listen for
412  * @param listener the listener which should be notified when the event occurs
413  *
414  * @exception IllegalArgumentException <ul>
415  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
416  * </ul>
417  * @exception SWTException <ul>
418  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
419  *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
420  * </ul>
421  *
422  * @see Listener
423  * @see #removeFilter
424  * @see #removeListener
425  * 
426  * @since 3.0 
427  */
428 public void addFilter (int eventType, Listener listener) {
429   checkDevice ();
430   if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
431   if (filterTable == null) filterTable = new EventTable ();
432   filterTable.hook (eventType, listener);
433 }
434 
435 void addGdkEvent (long /*int*/ event) {
436   if (gdkEvents == null) {
437     gdkEvents = new long /*int*/ [4];
438     gdkEventWidgets = new Widget [4];
439     gdkEventCount = 0;
440   }
441   if (gdkEventCount == gdkEvents.length) {
442     long /*int*/ [] newEvents = new long /*int*/ [gdkEventCount + 4];
443     System.arraycopy (gdkEvents, 0, newEvents, 0, gdkEventCount);
444     gdkEvents = newEvents;
445     Widget [] newWidgets = new Widget [gdkEventCount + 4];
446     System.arraycopy (gdkEventWidgets, 0, newWidgets, 0, gdkEventCount);
447     gdkEventWidgets = newWidgets;
448   }
449   Widget widget = null;
450   long /*int*/ handle = OS.gtk_get_event_widget (event);
451   if (handle != 0) {
452     do {
453       widget = getWidget (handle);
454     } while (widget == null && (handle = OS.gtk_widget_get_parent (handle)) != 0);
455   }
456   gdkEvents [gdkEventCount] = event;
457   gdkEventWidgets [gdkEventCount] = widget;
458   gdkEventCount++;
459 }
460 
461 /**
462  * Adds the listener to the collection of listeners who will
463  * be notifed when an event of the given type occurs. When the
464  * event does occur in the display, the listener is notified by
465  * sending it the <code>handleEvent()</code> message.
466  *
467  * @param eventType the type of event to listen for
468  * @param listener the listener which should be notified when the event occurs
469  *
470  * @exception IllegalArgumentException <ul>
471  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
472  * </ul>
473  * @exception SWTException <ul>
474  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
475  *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
476  * </ul>
477  *
478  * @see Listener
479  * @see #removeListener
480  * 
481  * @since 2.0 
482  */
483 public void addListener (int eventType, Listener listener) {
484   checkDevice ();
485   if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
486   if (eventTable == null) eventTable = new EventTable ();
487   eventTable.hook (eventType, listener);
488 }
489 
490 void addMouseHoverTimeout (long /*int*/ handle) {
491   if (mouseHoverId != 0) OS.gtk_timeout_remove (mouseHoverId);
492   mouseHoverId = OS.gtk_timeout_add (400, mouseHoverProc, handle);
493   mouseHoverHandle = handle;
494 }
495 
496 void addPopup (Menu menu) {
497   if (popups == null) popups = new Menu [4];
498   int length = popups.length;
499   for (int i=0; i<length; i++) {
500     if (popups [i] == menu) return;
501   }
502   int index = 0;
503   while (index < length) {
504     if (popups [index] == null) break;
505     index++;
506   }
507   if (index == length) {
508     Menu [] newPopups = new Menu [length + 4];
509     System.arraycopy (popups, 0, newPopups, 0, length);
510     popups = newPopups;
511   }
512   popups [index] = menu;
513 }
514 
515 void addWidget (long /*int*/ handle, Widget widget) {
516   if (handle == 0) return;
517   if (freeSlot == -1) {
518     int length = (freeSlot = indexTable.length) + GROW_SIZE;
519     int[] newIndexTable = new int[length];
520     Widget[] newWidgetTable = new Widget [length];
521     System.arraycopy (indexTable, 0, newIndexTable, 0, freeSlot);
522     System.arraycopy (widgetTable, 0, newWidgetTable, 0, freeSlot);
523     for (int i = freeSlot; i < length - 1; i++) {
524       newIndexTable[i] = i + 1;
525     }
526     newIndexTable[length - 1] = -1;
527     indexTable = newIndexTable;
528     widgetTable = newWidgetTable;
529   }
530   int index = freeSlot + 1;
531   OS.g_object_set_qdata (handle, SWT_OBJECT_INDEX, index);
532   int oldSlot = freeSlot;
533   freeSlot = indexTable[oldSlot];
534   indexTable [oldSlot] = -2;
535   widgetTable [oldSlot] = widget;
536 }
537 
538 /**
539  * Causes the <code>run()</code> method of the runnable to
540  * be invoked by the user-interface thread at the next 
541  * reasonable opportunity. The caller of this method continues 
542  * to run in parallel, and is not notified when the
543  * runnable has completed.
544  *
545  * @param runnable code to run on the user-interface thread.
546  *
547  * @exception SWTException <ul>
548  *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
549  * </ul>
550  * 
551  * @see #syncExec
552  */
553 public void asyncExec (Runnable runnable) {
554   if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
555   synchronizer.asyncExec (runnable);
556 }
557 
558 /**
559  * Causes the system hardware to emit a short sound
560  * (if it supports this capability).
561  * 
562  * @exception SWTException <ul>
563  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
564  *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
565  * </ul>
566  */
567 public void beep () {
568   if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
569   OS.gdk_beep();
570   OS.gdk_flush();
571 }
572 
573 protected void checkDevice () {
574   if (thread == null) error (SWT.ERROR_WIDGET_DISPOSED);
575   if (thread != Thread.currentThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
576   if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
577 }
578 
579 static synchronized void checkDisplay (Thread thread) {
580   for (int i=0; i<Displays.length; i++) {
581     if (Displays [i] != null && Displays [i].thread == thread) {
582       SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS);
583     }
584   }
585 }
586 
587 long /*int*/ checkIfEventProc (long /*int*/ display, long /*int*/ xEvent, long /*int*/ userData) {
588   OS.memmove (exposeEvent, xEvent, XExposeEvent.sizeof);
589   switch (exposeEvent.type) {
590     case OS.VisibilityNotify:
591     case OS.Expose:
592     case OS.GraphicsExpose:
593       break;
594     default:
595       return 0;
596   }
597   long /*int*/ window = OS.gdk_window_lookup (exposeEvent.window);
598   if (window == 0) return 0;
599   if (flushWindow != 0) {
600     if (flushAll) {
601       long /*int*/ tempWindow = window;
602       do {
603         if (tempWindow == flushWindow) break;
604       } while ((tempWindow = OS.gdk_window_get_parent (tempWindow)) != 0);
605       if (tempWindow != flushWindow) return 0;
606     } else {
607       if (window != flushWindow) return 0;
608     }
609   }
610   switch (exposeEvent.type) {
611     case OS.Expose:
612     case OS.GraphicsExpose: {
613       flushRect.x = exposeEvent.x;
614       flushRect.y = exposeEvent.y;
615       flushRect.width = exposeEvent.width;
616       flushRect.height = exposeEvent.height;
617       OS.gdk_window_invalidate_rect (window, flushRect, true);
618       exposeEvent.type = -1;
619       OS.memmove (xEvent, exposeEvent, XExposeEvent.sizeof);
620       break;
621     }
622     case OS.VisibilityNotify: {
623       OS.memmove (visibilityEvent, xEvent, XVisibilityEvent.sizeof);
624       OS.gdk_window_get_user_data (window, flushData);
625       long /*int*/ handle = flushData [0];
626       Widget widget = handle != 0 ? getWidget (handle) : null;
627       if (widget != null && widget instanceof Control) {
628         Control control = (Control) widget;
629         if (window == control.paintWindow ()) {
630           if (visibilityEvent.state == OS.VisibilityFullyObscured) {
631             control.state |= Widget.OBSCURED;
632           } else {
633             control.state &= ~Widget.OBSCURED;
634           }
635         }
636       }
637       break;
638     }
639   }
640   return 0;
641 }
642 
643 /**
644  * Checks that this class can be subclassed.
645  * <p>
646  * IMPORTANT: See the comment in <code>Widget.checkSubclass()</code>.
647  * </p>
648  *
649  * @exception SWTException <ul>
650  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
651  * </ul>
652  *
653  * @see Widget#checkSubclass
654  */
655 protected void checkSubclass () {
656   if (!isValidClass (getClass ())) error (SWT.ERROR_INVALID_SUBCLASS);
657 }
658 
659 /**
660  * Requests that the connection between SWT and the underlying
661  * operating system be closed.
662  *
663  * @exception SWTException <ul>
664  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
665  *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
666  * </ul>
667  *
668  * @see Device#dispose
669  * 
670  * @since 2.0
671  */
672 public void close () {
673   checkDevice ();
674   Event event = new Event ();
675   sendEvent (SWT.Close, event);
676   if (event.doit) dispose ();
677 }
678 
679 /**
680  * Creates the device in the operating system.  If the device
681  * does not have a handle, this method may do nothing depending
682  * on the device.
683  * <p>
684  * This method is called before <code>init</code>.
685  * </p>
686  *
687  * @param data the DeviceData which describes the receiver
688  *
689  * @see #init
690  */
691 protected void create (DeviceData data) {
692   checkSubclass ();
693   checkDisplay(thread = Thread.currentThread ());
694   createDisplay (data);
695   register ();
696   if (Default == null) Default = this;
697 }
698 
699 synchronized void createDisplay (DeviceData data) {
700   /*
701   * This code is intentionally commented.
702   */
703 //  if (!OS.g_thread_supported ()) {
704 //    OS.g_thread_init (0);
705 //    OS.gdk_threads_init ();
706 //  }
707   OS.gtk_set_locale();
708   if (!OS.gtk_init_check (new long /*int*/ [] {0}, null)) {
709     SWT.error (SWT.ERROR_NO_HANDLES);
710   }
711   OS.gtk_widget_set_default_direction (OS.GTK_TEXT_DIR_LTR);
712   OS.gdk_rgb_init ();
713   long /*int*/ ptr = OS.gtk_check_version (MAJOR, MINOR, MICRO);
714   if (ptr != 0) {
715     int length = OS.strlen (ptr);
716     byte [] buffer = new byte [length];
717     OS.memmove (buffer, ptr, length);
718     System.out.println ("***WARNING: " + new String (Converter.mbcsToWcs (null, buffer)));
719     System.out.println ("***WARNING: SWT requires GTK " + MAJOR+ "." + MINOR + "." + MICRO);
720     int major = OS.gtk_major_version (), minor = OS.gtk_minor_version (), micro = OS.gtk_micro_version ();
721     System.out.println ("***WARNING: Detected: " + major + "." + minor + "." + micro);
722   }
723   byte [] buffer = Converter.wcsToMbcs (null, APP_NAME, true);
724   OS.gdk_set_program_class (buffer);
725   byte [] flatStyle = Converter.wcsToMbcs (null, "style \"swt-flat\" { GtkToolbar::shadow-type = none } widget \"*swt-toolbar-flat*\" style : highest \"swt-flat\"", true);
726   OS.gtk_rc_parse_string (flatStyle);
727 
728   /* Initialize the event callback */
729   eventCallback = new Callback (this, "eventProc", 2);
730   eventProc = eventCallback.getAddress ();
731   if (eventProc == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
732   OS.gdk_event_handler_set (eventProc, 0, 0);
733 }
734 
735 long /*int*/[] createImage (String name) {
736   long /*int*/ style = OS.gtk_widget_get_default_style ();
737   byte[] buffer = Converter.wcsToMbcs (null, name, true);
738   long /*int*/ pixbuf = OS.gtk_icon_set_render_icon (
739     OS.gtk_icon_factory_lookup_default (buffer), style,
740     OS.GTK_TEXT_DIR_NONE, OS.GTK_STATE_NORMAL, -1, 0, 0);
741   if (pixbuf == 0) return null;
742   long /*int*/[] pixmap_return = new long /*int*/[1];
743   long /*int*/[] mask_return = new long /*int*/[1];
744   OS.gdk_pixbuf_render_pixmap_and_mask (pixbuf, pixmap_return, mask_return, 128);
745   OS.g_object_unref (pixbuf);
746   return new long /*int*/[] {pixmap_return [0], mask_return [0]};
747 }
748 
749 synchronized void deregister () {
750   for (int i=0; i<Displays.length; i++) {
751     if (this == Displays [i]) Displays [i] = null;
752   }
753 }
754 
755 /**
756  * Destroys the device in the operating system and releases
757  * the device's handle.  If the device does not have a handle,
758  * this method may do nothing depending on the device.
759  * <p>
760  * This method is called after <code>release</code>.
761  * </p>
762  * @see #dispose
763  * @see #release
764  */
765 protected void destroy () {
766   if (this == Default) Default = null;
767   deregister ();
768   destroyDisplay ();
769 }
770 
771 void destroyDisplay () {
772 }
773 
774 /**
775  * Returns the display which the given thread is the
776  * user-interface thread for, or null if the given thread
777  * is not a user-interface thread for any display.
778  *
779  * @param thread the user-interface thread
780  * @return the display for the given thread
781  */
782 public static synchronized Display findDisplay (Thread thread) {
783   for (int i=0; i<Displays.length; i++) {
784     Display display = Displays [i];
785     if (display != null && display.thread == thread) {
786       return display;
787     }
788   }
789   return null;
790 }
791 
792 /**
793  * Causes the <code>run()</code> method of the runnable to
794  * be invoked by the user-interface thread just before the
795  * receiver is disposed.
796  *
797  * @param runnable code to run at dispose time.
798  * 
799  * @exception SWTException <ul>
800  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
801  *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
802  * </ul>
803  */
804 public void disposeExec (Runnable runnable) {
805   checkDevice ();
806   if (disposeList == null) disposeList = new Runnable [4];
807   for (int i=0; i<disposeList.length; i++) {
808     if (disposeList [i] == null) {
809       disposeList [i] = runnable;
810       return;
811     }
812   }
813   Runnable [] newDisposeList = new Runnable [disposeList.length + 4];
814   System.arraycopy (disposeList, 0, newDisposeList, 0, disposeList.length);
815   newDisposeList [disposeList.length] = runnable;
816   disposeList = newDisposeList;
817 }
818 
819 /**
820  * Does whatever display specific cleanup is required, and then
821  * uses the code in <code>SWTError.error</code> to handle the error.
822  *
823  * @param code the descriptive error code
824  *
825  * @see SWTError#error
826  */
827 void error (int code) {
828   SWT.error (code);
829 }
830 
831 long /*int*/ eventProc (long /*int*/ event, long /*int*/ data) {
832   OS.memmove (gdkEvent, event, GdkEventButton.sizeof);
833   boolean dispatch = true;
834   if (dispatchEvents != null) {
835     dispatch = false;
836     for (int i = 0; i < dispatchEvents.length; i++) {
837       if (gdkEvent.type == dispatchEvents [i]) {
838         dispatch = true;
839         break;
840       }
841     }
842   }
843   if (!dispatch) {
844     addGdkEvent (OS.gdk_event_copy (event));
845     return 0;
846   }
847   Control control = null;
848   long /*int*/ window = 0;
849   switch (gdkEvent.type) {
850     case OS.GDK_ENTER_NOTIFY:
851     case OS.GDK_LEAVE_NOTIFY:
852     case OS.GDK_BUTTON_PRESS:
853     case OS.GDK_2BUTTON_PRESS: 
854     case OS.GDK_3BUTTON_PRESS:
855     case OS.GDK_BUTTON_RELEASE: 
856     case OS.GDK_MOTION_NOTIFY:  {
857       window = gdkEvent.window;
858       long /*int*/ [] user_data = new long /*int*/ [1];
859       do {
860         OS.gdk_window_get_user_data (window, user_data);
861         long /*int*/ handle = user_data [0];
862         if (handle != 0) {
863           Widget widget = getWidget (handle);
864           if (widget != null && widget instanceof Control) {
865             control = (Control) widget;
866             break;
867           }
868         }
869       } while ((window = OS.gdk_window_get_parent (window)) != 0);
870     }
871   }
872   Shell shell = null;
873   if (control != null ) {
874     shell = control.getShell ();
875     if ((shell.style & SWT.ON_TOP) != 0) {
876       OS.gtk_grab_add (shell.shellHandle);
877     }
878   }
879   OS.gtk_main_do_event (event);
880   if (dispatchEvents == null) putGdkEvents ();
881   if (control != null ) {
882     if (shell != null && !shell.isDisposed () && (shell.style & SWT.ON_TOP) != 0) {
883       OS.gtk_grab_remove (shell.shellHandle);
884     }
885   }
886   return 0;
887 }
888 
889 /**
890  * Given the operating system handle for a widget, returns
891  * the instance of the <code>Widget</code> subclass which
892  * represents it in the currently running application, if
893  * such exists, or null if no matching widget can be found.
894  *
895  * @param handle the handle for the widget
896  * @return the SWT widget that the handle represents
897  *
898  * @exception SWTException <ul>
899  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
900  *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
901  * </ul>
902  */
903 public Widget findWidget (long /*int*/ handle) {
904   checkDevice ();
905   return getWidget (handle);
906 }
907 
908 void flushExposes (long /*int*/ window, boolean all) {
909   OS.gdk_flush ();
910   OS.gdk_flush ();
911   if (OS.GDK_WINDOWING_X11 ()) {
912     this.flushWindow = window;
913     this.flushAll = all;
914     long /*int*/ xDisplay = OS.GDK_DISPLAY ();
915     long /*int*/ xEvent = OS.g_malloc (XEvent.sizeof);
916     OS.XCheckIfEvent (xDisplay, xEvent, checkIfEventProc, 0);
917     OS.g_free (xEvent);
918     this.flushWindow = 0;
919   }
920 }
921 
922 /**
923  * Returns the currently active <code>Shell</code>, or null
924  * if no shell belonging to the currently running application
925  * is active.
926  *
927  * @return the active shell or null
928  *
929  * @exception SWTException <ul>
930  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
931  *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
932  * </ul>
933  */
934 public Shell getActiveShell () {
935   checkDevice ();
936   Shell [] shells = getShells ();
937   for (int i=0; i<shells.length; i++) {
938      if (shells [i].hasFocus) return shells [i];
939   }
940   return null;
941 }
942 
943 /**
944  * Returns a rectangle describing the receiver's size and location.
945  *
946  * @return the bounding rectangle
947  *
948  * @exception SWTException <ul>
949  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
950  *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
951  * </ul>
952  */
953 public Rectangle getBounds () {
954   checkDevice ();
955   return new Rectangle (0, 0, OS.gdk_screen_width (), OS.gdk_screen_height ());
956 }
957 
958 /**
959  * Returns the display which the currently running thread is
960  * the user-interface thread for, or null if the currently
961  * running thread is not a user-interface thread for any display.
962  *
963  * @return the current display
964  */
965 public static synchronized Display getCurrent () {
966   Thread current = Thread.currentThread ();
967   for (int i=0; i<Displays.length; i++) {
968     Display display = Displays [i];
969     if (display != null && display.thread == current) return display;
970   }
971   return null;
972 }
973 
974 /**
975  * Returns the control which the on-screen pointer is currently
976  * over top of, or null if it is not currently over one of the
977  * controls built by the currently running application.
978  *
979  * @return the control under the cursor
980  *
981  * @exception SWTException <ul>
982  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
983  *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
984  * </ul>
985  */
986 public Control getCursorControl () {
987   checkDevice();
988   int[] x = new int[1], y = new int[1];
989   long /*int*/ window = OS.gdk_window_at_pointer (x,y);
990   if (window == 0) return null;
991   long /*int*/ [] user_data = new long /*int*/ [1];
992   OS.gdk_window_get_user_data (window, user_data);
993   long /*int*/ handle = user_data [0];
994   if (handle == 0) return null;
995   do {
996     Widget widget = getWidget (handle);
997     if (widget != null && widget instanceof Control) {
998       Control control = (Control) widget;
999       if (control.isEnabled ()) return control;
1000    }
1001  } while ((handle = OS.gtk_widget_get_parent (handle)) != 0);
1002  return null;
1003}
1004
1005boolean filterEvent (Event event) {
1006  if (filterTable != null) filterTable.sendEvent (event);
1007  return false;
1008}
1009
1010boolean filters (int eventType) {
1011  if (filterTable == null) return false;
1012  return filterTable.hooks (eventType);
1013}
1014
1015long /*int*/ filterProc (long /*int*/ xEvent, long /*int*/ gdkEvent, long /*int*/ data) {
1016  Widget widget = getWidget (data);
1017  if (widget == null) return 0;
1018  return widget.filterProc (xEvent, gdkEvent, data);
1019}
1020
1021/**
1022 * Returns the location of the on-screen pointer relative
1023 * to the top left corner of the screen.
1024 *
1025 * @return the cursor location
1026 *
1027 * @exception SWTException <ul>
1028 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1029 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1030 * </ul>
1031 */
1032public Point getCursorLocation () {
1033  checkDevice ();
1034  int [] x = new int [1], y = new int [1];
1035  OS.gdk_window_get_pointer (0, x, y, null);
1036  return new Point (x [0], y [0]);
1037}
1038
1039/**
1040 * Returns an array containing the recommended cursor sizes.
1041 *
1042 * @return the array of cursor sizes
1043 *
1044 * @exception SWTException <ul>
1045 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1046 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1047 * </ul>
1048 * 
1049 * @since 3.0
1050 */
1051public Point [] getCursorSizes () {
1052  checkDevice ();
1053  return new Point [] {new Point (16, 16), new Point (32, 32)}; 
1054}
1055
1056/**
1057 * Returns the application defined property of the receiver
1058 * with the specified name, or null if it has not been set.
1059 * <p>
1060 * Applications may have associated arbitrary objects with the
1061 * receiver in this fashion. If the objects stored in the
1062 * properties need to be notified when the display is disposed
1063 * of, it is the application's responsibility provide a
1064 * <code>disposeExec()</code> handler which does so.
1065 * </p>
1066 *
1067 * @param key the name of the property
1068 * @return the value of the property or null if it has not been set
1069 *
1070 * @exception IllegalArgumentException <ul>
1071 *    <li>ERROR_NULL_ARGUMENT - if the key is null</li>
1072 * </ul>
1073 * @exception SWTException <ul>
1074 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1075 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1076 * </ul>
1077 *
1078 * @see #setData
1079 * @see #disposeExec
1080 */
1081public Object getData (String key) {
1082  checkDevice ();
1083  if (key == null) error (SWT.ERROR_NULL_ARGUMENT);
1084  if (key.equals (DISPATCH_EVENT_KEY)) {
1085    return dispatchEvents;
1086  }
1087  if (keys == null) return null;
1088  for (int i=0; i<keys.length; i++) {
1089    if (keys [i].equals (key)) return values [i];
1090  }
1091  return null;
1092}
1093
1094/**
1095 * Returns the application defined, display specific data
1096 * associated with the receiver, or null if it has not been
1097 * set. The <em>display specific data</em> is a single,
1098 * unnamed field that is stored with every display. 
1099 * <p>
1100 * Applications may put arbitrary objects in this field. If
1101 * the object stored in the display specific data needs to
1102 * be notified when the display is disposed of, it is the
1103 * application's responsibility provide a
1104 * <code>disposeExec()</code> handler which does so.
1105 * </p>
1106 *
1107 * @return the display specific data
1108 *
1109 * @exception SWTException <ul>
1110 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1111 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1112 * </ul>
1113 *
1114 * @see #setData
1115 * @see #disposeExec
1116 */
1117public Object getData () {
1118  checkDevice ();
1119  return data;
1120}
1121
1122/**
1123 * Returns a point whose x coordinate is the horizontal
1124 * dots per inch of the display, and whose y coordinate
1125 * is the vertical dots per inch of the display.
1126 *
1127 * @return the horizontal and vertical DPI
1128 *
1129 * @exception SWTException <ul>
1130 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1131 * </ul>
1132 */
1133public Point getDPI () {
1134  checkDevice ();
1135  int widthMM = OS.gdk_screen_width_mm ();
1136  int width = OS.gdk_screen_width ();
1137  int dpi = Compatibility.round (254 * width, widthMM * 10);
1138  return new Point (dpi, dpi);
1139}
1140
1141/**
1142 * Returns the default display. One is created (making the
1143 * thread that invokes this method its user-interface thread)
1144 * if it did not already exist.
1145 *
1146 * @return the default display
1147 */
1148public static synchronized Display getDefault () {
1149  if (Default == null) Default = new Display ();
1150  return Default;
1151}
1152
1153static boolean isValidClass (Class clazz) {
1154  String name = clazz.getName ();
1155  int index = name.lastIndexOf ('.');
1156  return name.substring (0, index + 1).equals (PACKAGE_PREFIX);
1157}
1158
1159/**
1160 * Returns the button dismissal alignment, one of <code>LEFT</code> or <code>RIGHT</code>.
1161 * The button dismissal alignment is the ordering that should be used when positioning the
1162 * default dismissal button for a dialog.  For example, in a dialog that contains an OK and
1163 * CANCEL button, on platforms where the button dismissal alignment is <code>LEFT</code>, the
1164 * button ordering should be OK/CANCEL.  When button dismissal alignment is <code>RIGHT</code>,
1165 * the button ordering should be CANCEL/OK.
1166 *
1167 * @return the button dismissal order
1168 *
1169 * @exception SWTException <ul>
1170 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1171 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1172 * </ul>
1173 * 
1174 * @since 2.1
1175 */
1176public int getDismissalAlignment () {
1177  checkDevice ();
1178  return SWT.RIGHT;
1179}
1180
1181/**
1182 * Returns the longest duration, in milliseconds, between
1183 * two mouse button clicks that will be considered a
1184 * <em>double click</em> by the underlying operating system.
1185 *
1186 * @return the double click time
1187 *
1188 * @exception SWTException <ul>
1189 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1190 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1191 * </ul>
1192 */
1193public int getDoubleClickTime () {
1194  checkDevice ();
1195  return DOUBLE_CLICK_TIME;
1196}
1197
1198/**
1199 * Returns the control which currently has keyboard focus,
1200 * or null if keyboard events are not currently going to
1201 * any of the controls built by the currently running
1202 * application.
1203 *
1204 * @return the control under the cursor
1205 *
1206 * @exception SWTException <ul>
1207 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1208 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1209 * </ul>
1210 */
1211public Control getFocusControl () {
1212  checkDevice ();
1213  Shell shell = getActiveShell ();
1214  if (shell == null) return null;
1215  long /*int*/ shellHandle = shell.shellHandle;
1216  long /*int*/ handle = OS.gtk_window_get_focus (shellHandle);
1217  if (handle == 0) return null;
1218  do {
1219    Widget widget = getWidget (handle);
1220    if (widget != null && widget instanceof Control) {
1221      Control control = (Control) widget;
1222      return control.isEnabled () ? control : null;
1223    }
1224  } while ((handle = OS.gtk_widget_get_parent (handle)) != 0);
1225  return null;
1226}
1227
1228/**
1229 * Returns true when the high contrast mode is enabled.
1230 * Otherwise, false is returned.
1231 * <p>
1232 * Note: This operation is a hint and is not supported on
1233 * platforms that do not have this concept.
1234 * </p>
1235 *
1236 * @return the high contrast mode
1237 *
1238 * @exception SWTException <ul>
1239 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1240 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1241 * </ul>
1242 * 
1243 * @since 3.0
1244 */
1245public boolean getHighContrast () {
1246  checkDevice ();
1247  return false;
1248}
1249
1250public int getDepth () {
1251  checkDevice ();
1252  GdkVisual visual = new GdkVisual ();
1253  OS.memmove (visual, OS.gdk_visual_get_system());
1254  return visual.depth;
1255}
1256
1257/**
1258 * Returns the maximum allowed depth of icons on this display.
1259 * On some platforms, this may be different than the actual
1260 * depth of the display.
1261 *
1262 * @return the maximum icon depth
1263 *
1264 * @exception SWTException <ul>
1265 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1266 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1267 * </ul>
1268 */
1269public int getIconDepth () {
1270  checkDevice ();
1271  return getDepth ();
1272}
1273
1274/**
1275 * Returns an array containing the recommended icon sizes.
1276 *
1277 * @return the array of icon sizes
1278 *
1279 * @exception SWTException <ul>
1280 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1281 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1282 * </ul>
1283 * 
1284 * @see Decorations#setImages(Image[])
1285 * 
1286 * @since 3.0
1287 */
1288public Point [] getIconSizes () {
1289  checkDevice ();
1290  return new Point [] {new Point (16, 16), new Point (32, 32)}; 
1291}
1292
1293int getLastEventTime () {
1294  return OS.gtk_get_current_event_time ();
1295}
1296
1297int getMessageCount () {
1298  return synchronizer.getMessageCount ();
1299}
1300
1301/**
1302 * Returns an array of monitors attached to the device.
1303 * 
1304 * @return the array of monitors
1305 * 
1306 * @since 3.0
1307 */
1308public Monitor [] getMonitors () {
1309  checkDevice ();
1310  Monitor [] monitors = null;
1311  long /*int*/ screen = OS.gdk_screen_get_default ();
1312  if (screen != 0) {
1313    int monitorCount = OS.gdk_screen_get_n_monitors (screen);
1314    if (monitorCount > 0) {
1315      monitors = new Monitor [monitorCount];
1316      GdkRectangle dest = new GdkRectangle ();
1317      for (int i = 0; i < monitorCount; i++) {
1318        OS.gdk_screen_get_monitor_geometry (screen, i, dest);
1319        Monitor monitor = new Monitor ();
1320        monitor.handle = i;
1321        monitor.x = dest.x;
1322        monitor.y = dest.y;
1323        monitor.width = dest.width;
1324        monitor.height = dest.height;
1325        monitor.clientX = monitor.x;
1326        monitor.clientY = monitor.y;
1327        monitor.clientWidth = monitor.width;
1328        monitor.clientHeight = monitor.height;
1329        monitors [i] = monitor;
1330      }
1331    }
1332  }
1333  if (monitors == null) {
1334    /* No multimonitor support detected, default to one monitor */
1335    Monitor monitor = new Monitor ();
1336    Rectangle bounds = getBounds ();
1337    monitor.x = bounds.x;
1338    monitor.y = bounds.y;
1339    monitor.width = bounds.width;
1340    monitor.height = bounds.height;
1341    monitor.clientX = monitor.x;
1342    monitor.clientY = monitor.y;
1343    monitor.clientWidth = monitor.width;
1344    monitor.clientHeight = monitor.height;
1345    monitors = new Monitor [] { monitor };      
1346  }
1347  return monitors;
1348}
1349
1350/**
1351 * Returns the primary monitor for that device.
1352 * 
1353 * @return the primary monitor
1354 * 
1355 * @since 3.0
1356 */
1357public Monitor getPrimaryMonitor () {
1358  checkDevice ();
1359  Monitor [] monitors = getMonitors ();
1360  return monitors [0];
1361}
1362
1363/**
1364 * Returns an array containing all shells which have not been
1365 * disposed and have the receiver as their display.
1366 *
1367 * @return the receiver's shells
1368 *
1369 * @exception SWTException <ul>
1370 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1371 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1372 * </ul>
1373 */
1374public Shell [] getShells () {
1375  checkDevice ();
1376  int length = 0;
1377  for (int i=0; i<widgetTable.length; i++) {
1378    Widget widget = widgetTable [i];
1379    if (widget != null && widget instanceof Shell) length++;
1380  }
1381  int index = 0;
1382  Shell [] result = new Shell [length];
1383  for (int i=0; i<widgetTable.length; i++) {
1384    Widget widget = widgetTable [i];
1385    if (widget != null && widget instanceof Shell) {
1386      int j = 0;
1387      while (j < index) {
1388        if (result [j] == widget) break;
1389        j++;
1390      }
1391      if (j == index) result [index++] = (Shell) widget;
1392    }
1393  }
1394  if (index == length) return result;
1395  Shell [] newResult = new Shell [index];
1396  System.arraycopy (result, 0, newResult, 0, index);
1397  return newResult;
1398}
1399
1400/**
1401 * Returns the thread that has invoked <code>syncExec</code>
1402 * or null if no such runnable is currently being invoked by
1403 * the user-interface thread.
1404 * <p>
1405 * Note: If a runnable invoked by asyncExec is currently
1406 * running, this method will return null.
1407 * </p>
1408 *
1409 * @return the receiver's sync-interface thread
1410 * 
1411 * @exception SWTException <ul>
1412 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1413 * </ul>
1414 */
1415public Thread getSyncThread () {
1416  if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
1417  return synchronizer.syncThread;
1418}
1419
1420/**
1421 * Returns the matching standard color for the given
1422 * constant, which should be one of the color constants
1423 * specified in class <code>SWT</code>. Any value other
1424 * than one of the SWT color constants which is passed
1425 * in will result in the color black. This color should
1426 * not be free'd because it was allocated by the system,
1427 * not the application.
1428 *
1429 * @param id the color constant
1430 * @return the matching color
1431 *
1432 * @exception SWTException <ul>
1433 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1434 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1435 * </ul>
1436 *
1437 * @see SWT
1438 */
1439public Color getSystemColor (int id) {
1440  checkDevice ();
1441  GdkColor gdkColor = null;
1442  switch (id) {
1443    case SWT.COLOR_INFO_FOREGROUND:           gdkColor = COLOR_INFO_FOREGROUND; break;
1444    case SWT.COLOR_INFO_BACKGROUND:           gdkColor = COLOR_INFO_BACKGROUND; break;
1445    case SWT.COLOR_TITLE_FOREGROUND:          gdkColor = COLOR_TITLE_FOREGROUND; break;
1446    case SWT.COLOR_TITLE_BACKGROUND:          gdkColor = COLOR_TITLE_BACKGROUND; break;
1447    case SWT.COLOR_TITLE_BACKGROUND_GRADIENT:      gdkColor = COLOR_TITLE_BACKGROUND_GRADIENT; break;
1448    case SWT.COLOR_TITLE_INACTIVE_FOREGROUND:      gdkColor = COLOR_TITLE_INACTIVE_FOREGROUND; break;
1449    case SWT.COLOR_TITLE_INACTIVE_BACKGROUND:      gdkColor = COLOR_TITLE_INACTIVE_BACKGROUND; break;
1450    case SWT.COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT:  gdkColor = COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT; break;
1451    case SWT.COLOR_WIDGET_DARK_SHADOW:          gdkColor = COLOR_WIDGET_DARK_SHADOW; break;
1452    case SWT.COLOR_WIDGET_NORMAL_SHADOW:        gdkColor = COLOR_WIDGET_NORMAL_SHADOW; break;
1453    case SWT.COLOR_WIDGET_LIGHT_SHADOW:         gdkColor = COLOR_WIDGET_LIGHT_SHADOW; break;
1454    case SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW:        gdkColor = COLOR_WIDGET_HIGHLIGHT_SHADOW; break;
1455    case SWT.COLOR_WIDGET_BACKGROUND:           gdkColor = COLOR_WIDGET_BACKGROUND; break;
1456    case SWT.COLOR_WIDGET_FOREGROUND:           gdkColor = COLOR_WIDGET_FOREGROUND; break;
1457    case SWT.COLOR_WIDGET_BORDER:             gdkColor = COLOR_WIDGET_BORDER; break;
1458    case SWT.COLOR_LIST_FOREGROUND:           gdkColor = COLOR_LIST_FOREGROUND; break;
1459    case SWT.COLOR_LIST_BACKGROUND:           gdkColor = COLOR_LIST_BACKGROUND; break;
1460    case SWT.COLOR_LIST_SELECTION:             gdkColor = COLOR_LIST_SELECTION; break;
1461    case SWT.COLOR_LIST_SELECTION_TEXT:         gdkColor = COLOR_LIST_SELECTION_TEXT; break;
1462    default:
1463      return super.getSystemColor (id);  
1464  }
1465  if (gdkColor == null) return super.getSystemColor (SWT.COLOR_BLACK);
1466  return Color.gtk_new (this, gdkColor);
1467}
1468
1469/**
1470 * Returns the matching standard platform cursor for the given
1471 * constant, which should be one of the cursor constants
1472 * specified in class <code>SWT</code>. This cursor should
1473 * not be free'd because it was allocated by the system,
1474 * not the application.  A value of <code>null</code> will
1475 * be returned if the supplied constant is not an swt cursor
1476 * constant. 
1477 *
1478 * @param id the swt cursor constant
1479 * @return the corresponding cursor or <code>null</code>
1480 *
1481 * @exception SWTException <ul>
1482 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1483 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1484 * </ul>
1485 *
1486 * @see SWT#CURSOR_ARROW
1487 * @see SWT#CURSOR_WAIT
1488 * @see SWT#CURSOR_CROSS
1489 * @see SWT#CURSOR_APPSTARTING
1490 * @see SWT#CURSOR_HELP
1491 * @see SWT#CURSOR_SIZEALL
1492 * @see SWT#CURSOR_SIZENESW
1493 * @see SWT#CURSOR_SIZENS
1494 * @see SWT#CURSOR_SIZENWSE
1495 * @see SWT#CURSOR_SIZEWE
1496 * @see SWT#CURSOR_SIZEN
1497 * @see SWT#CURSOR_SIZES
1498 * @see SWT#CURSOR_SIZEE
1499 * @see SWT#CURSOR_SIZEW
1500 * @see SWT#CURSOR_SIZENE
1501 * @see SWT#CURSOR_SIZESE
1502 * @see SWT#CURSOR_SIZESW
1503 * @see SWT#CURSOR_SIZENW
1504 * @see SWT#CURSOR_UPARROW
1505 * @see SWT#CURSOR_IBEAM
1506 * @see SWT#CURSOR_NO
1507 * @see SWT#CURSOR_HAND
1508 * 
1509 * @since 3.0
1510 */
1511public Cursor getSystemCursor (int id) {
1512  checkDevice ();
1513  if (!(0 <= id && id < cursors.length)) return null;
1514  if (cursors [id] == null) {
1515    cursors [id] = new Cursor (this, id);
1516  }
1517  return cursors [id];
1518}
1519
1520/**
1521 * Returns the matching standard platform image for the given
1522 * constant, which should be one of the icon constants
1523 * specified in class <code>SWT</code>. This image should
1524 * not be free'd because it was allocated by the system,
1525 * not the application.  A value of <code>null</code> will
1526 * be returned either if the supplied constant is not an
1527 * swt icon constant or if the platform does not define an
1528 * image that corresponds to the constant. 
1529 *
1530 * @param id the swt icon constant
1531 * @return the corresponding image or <code>null</code>
1532 *
1533 * @exception SWTException <ul>
1534 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1535 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1536 * </ul>
1537 *
1538 * @see SWT#ICON_ERROR
1539 * @see SWT#ICON_INFORMATION
1540 * @see SWT#ICON_QUESTION
1541 * @see SWT#ICON_WARNING
1542 * @see SWT#ICON_WORKING
1543 * 
1544 * @since 3.0
1545 */
1546public Image getSystemImage (int id) {
1547  long /*int*/ imagePixmap = 0, imageMask = 0;
1548  switch (id) {
1549    case SWT.ICON_ERROR:
1550      if (errorPixmap == 0) {
1551        long /*int*/[] image = createImage ("gtk-dialog-error");
1552        if (image != null) {
1553          errorPixmap = image [0];
1554          errorMask = image [1];
1555        }
1556      }
1557      imagePixmap = errorPixmap;
1558      imageMask = errorMask;
1559      break;
1560    case SWT.ICON_INFORMATION:
1561    case SWT.ICON_WORKING:
1562      if (infoPixmap == 0) {
1563        long /*int*/[] image = createImage ("gtk-dialog-info");
1564        if (image != null) {
1565          infoPixmap = image [0];
1566          infoMask = image [1];
1567        }
1568      }
1569      imagePixmap = infoPixmap;
1570      imageMask = infoMask;
1571      break;
1572    case SWT.ICON_QUESTION:
1573      if (questionPixmap == 0) {
1574        long /*int*/[] image = createImage ("gtk-dialog-question");
1575        if (image != null) {
1576          questionPixmap = image [0];
1577          questionMask = image [1];
1578        }
1579      }
1580      imagePixmap = questionPixmap;
1581      imageMask = questionMask;
1582      break;
1583    case SWT.ICON_WARNING:
1584      if (warningPixmap == 0) {
1585        long /*int*/[] image = createImage ("gtk-dialog-warning");
1586        if (image != null) {
1587          warningPixmap = image [0];
1588          warningMask = image [1];
1589        }
1590      }
1591      imagePixmap = warningPixmap;
1592      imageMask = warningMask;
1593      break;
1594  }
1595  if (imagePixmap == 0) return null;
1596  return Image.gtk_new (this, SWT.ICON, imagePixmap, imageMask);
1597}
1598
1599void initializeSystemResources () {
1600  long /*int*/ shellHandle = OS.gtk_window_new (OS.GTK_WINDOW_TOPLEVEL);
1601  if (shellHandle == 0) SWT.error (SWT.ERROR_NO_HANDLES);
1602  OS.gtk_widget_realize (shellHandle);
1603  
1604  long /*int*/ tooltipShellHandle = OS.gtk_window_new (OS.GTK_WINDOW_POPUP);
1605  if (tooltipShellHandle == 0) SWT.error (SWT.ERROR_NO_HANDLES);
1606  byte[] gtk_tooltips = Converter.wcsToMbcs (null, "gtk-tooltips", true);
1607  OS.gtk_widget_set_name (tooltipShellHandle, gtk_tooltips);
1608  OS.gtk_widget_realize (tooltipShellHandle);
1609
1610  GdkColor gdkColor;
1611  long /*int*/ style = OS.gtk_widget_get_style (shellHandle);  
1612  long /*int*/ tooltipStyle = OS.gtk_widget_get_style (tooltipShellHandle);
1613  
1614  defaultFont = OS.pango_font_description_copy (OS.gtk_style_get_font_desc (style));
1615
1616  gdkColor = new GdkColor();
1617  OS.gtk_style_get_black (style, gdkColor);
1618  COLOR_WIDGET_DARK_SHADOW = gdkColor;
1619  
1620  gdkColor = new GdkColor();
1621  OS.gtk_style_get_dark (style, OS.GTK_STATE_NORMAL, gdkColor);
1622  COLOR_WIDGET_NORMAL_SHADOW = gdkColor;
1623
1624  gdkColor = new GdkColor();
1625  OS.gtk_style_get_bg (style, OS.GTK_STATE_NORMAL, gdkColor);
1626  COLOR_WIDGET_LIGHT_SHADOW = gdkColor;
1627
1628  gdkColor = new GdkColor();
1629  OS.gtk_style_get_light (style, OS.GTK_STATE_NORMAL, gdkColor);
1630  COLOR_WIDGET_HIGHLIGHT_SHADOW = gdkColor;
1631
1632  gdkColor = new GdkColor();
1633  OS.gtk_style_get_fg (style, OS.GTK_STATE_NORMAL, gdkColor);
1634  COLOR_WIDGET_FOREGROUND = gdkColor;
1635
1636  gdkColor = new GdkColor();
1637  OS.gtk_style_get_bg (style, OS.GTK_STATE_NORMAL, gdkColor);
1638  COLOR_WIDGET_BACKGROUND = gdkColor;
1639
1640  gdkColor = new GdkColor();
1641  OS.gtk_style_get_text (style, OS.GTK_STATE_NORMAL, gdkColor);
1642  COLOR_TEXT_FOREGROUND = gdkColor;
1643
1644  gdkColor = new GdkColor();
1645  OS.gtk_style_get_base (style, OS.GTK_STATE_NORMAL, gdkColor);
1646  COLOR_TEXT_BACKGROUND = gdkColor;
1647
1648  gdkColor = new GdkColor();
1649  OS.gtk_style_get_text (style, OS.GTK_STATE_NORMAL, gdkColor);
1650  COLOR_LIST_FOREGROUND = gdkColor;
1651
1652  gdkColor = new GdkColor();
1653  OS.gtk_style_get_base (style, OS.GTK_STATE_NORMAL, gdkColor);
1654  COLOR_LIST_BACKGROUND = gdkColor;
1655
1656  gdkColor = new GdkColor();
1657  OS.gtk_style_get_text (style, OS.GTK_STATE_SELECTED, gdkColor);
1658  COLOR_LIST_SELECTION_TEXT = gdkColor;
1659
1660  gdkColor = new GdkColor();
1661  OS.gtk_style_get_base (style, OS.GTK_STATE_SELECTED, gdkColor);
1662  COLOR_LIST_SELECTION = gdkColor;
1663
1664  gdkColor = new GdkColor();
1665  OS.gtk_style_get_fg (tooltipStyle, OS.GTK_STATE_NORMAL, gdkColor);
1666  COLOR_INFO_FOREGROUND = gdkColor;
1667
1668  gdkColor = new GdkColor();
1669  OS.gtk_style_get_bg (tooltipStyle, OS.GTK_STATE_NORMAL, gdkColor);
1670  COLOR_INFO_BACKGROUND = gdkColor;
1671  
1672  gdkColor = new GdkColor();
1673  OS.gtk_style_get_bg (style, OS.GTK_STATE_SELECTED, gdkColor);
1674  COLOR_TITLE_BACKGROUND = gdkColor;
1675  
1676  gdkColor = new GdkColor();
1677  OS.gtk_style_get_fg (style, OS.GTK_STATE_SELECTED, gdkColor);
1678  COLOR_TITLE_FOREGROUND = gdkColor;
1679  
1680  gdkColor = new GdkColor();
1681  OS.gtk_style_get_light (style, OS.GTK_STATE_SELECTED, gdkColor);
1682  COLOR_TITLE_BACKGROUND_GRADIENT = gdkColor;
1683  
1684  gdkColor = new GdkColor();
1685  OS.gtk_style_get_bg (style, OS.GTK_STATE_INSENSITIVE, gdkColor);
1686  COLOR_TITLE_INACTIVE_BACKGROUND = gdkColor;
1687  
1688  gdkColor = new GdkColor();
1689  OS.gtk_style_get_fg (style, OS.GTK_STATE_INSENSITIVE, gdkColor);
1690  COLOR_TITLE_INACTIVE_FOREGROUND = gdkColor;
1691  
1692  gdkColor = new GdkColor();
1693  OS.gtk_style_get_light (style, OS.GTK_STATE_INSENSITIVE, gdkColor);
1694  COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT = gdkColor;
1695
1696  OS.gtk_widget_destroy (tooltipShellHandle);
1697  OS.gtk_widget_destroy (shellHandle);
1698}
1699
1700/**
1701 * Returns a reasonable font for applications to use.
1702 * On some platforms, this will match the "default font"
1703 * or "system font" if such can be found.  This font
1704 * should not be free'd because it was allocated by the
1705 * system, not the application.
1706 * <p>
1707 * Typically, applications which want the default look
1708 * should simply not set the font on the widgets they
1709 * create. Widgets are always created with the correct
1710 * default font for the class of user-interface component
1711 * they represent.
1712 * </p>
1713 *
1714 * @return a font
1715 *
1716 * @exception SWTException <ul>
1717 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1718 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1719 * </ul>
1720 */
1721public Font getSystemFont () {
1722  checkDevice ();
1723  return Font.gtk_new (this, defaultFont);
1724}
1725
1726/**
1727 * Returns the single instance of the system tray.
1728 *
1729 * @return the receiver's user-interface thread
1730 * 
1731 * @exception SWTException <ul>
1732 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1733 * </ul>
1734 *
1735 * @since 3.0
1736 */
1737public Tray getSystemTray () {
1738  if (tray != null) return tray;
1739  return tray = new Tray (this, SWT.NULL);
1740}
1741
1742/**
1743 * Returns the user-interface thread for the receiver.
1744 *
1745 * @return the receiver's user-interface thread
1746 * 
1747 * @exception SWTException <ul>
1748 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1749 * </ul>
1750 */
1751public Thread getThread () {
1752  if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
1753  return thread;
1754}
1755
1756Widget getWidget (long /*int*/ handle) {
1757  if (handle == 0) return null;
1758  long /*int*/ index = OS.g_object_get_qdata (handle, SWT_OBJECT_INDEX) - 1;
1759  if (0 <= index && index < widgetTable.length) return widgetTable [(int)/*64*/index];
1760  return null;  
1761}
1762
1763/**
1764 * Initializes any internal resources needed by the
1765 * device.
1766 * <p>
1767 * This method is called after <code>create</code>.
1768 * </p>
1769 * 
1770 * @see #create
1771 */
1772protected void init () {
1773  super.init ();
1774  initializeCallbacks ();
1775  initializeSystemResources ();
1776  initializeWidgetTable ();
1777}
1778
1779void initializeCallbacks () {
1780  windowCallback2 = new Callback (this, "windowProc", 2);
1781  windowProc2 = windowCallback2.getAddress ();
1782  if (windowProc2 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
1783    
1784  windowCallback3 = new Callback (this, "windowProc", 3);
1785  windowProc3 = windowCallback3.getAddress ();
1786  if (windowProc3 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);  
1787  
1788  windowCallback4 = new Callback (this, "windowProc", 4);
1789  windowProc4 = windowCallback4.getAddress ();
1790  if (windowProc4 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);  
1791  
1792  windowCallback5 = new Callback (this, "windowProc", 5);
1793  windowProc5 = windowCallback5.getAddress ();
1794  if (windowProc5 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
1795  
1796  timerCallback = new Callback (this, "timerProc", 1);
1797  timerProc = timerCallback.getAddress ();
1798  if (timerProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
1799
1800  windowTimerCallback = new Callback (this, "windowTimerProc", 1);
1801  windowTimerProc = windowTimerCallback.getAddress ();
1802  if (windowTimerProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
1803  
1804  mouseHoverCallback = new Callback (this, "mouseHoverProc", 1);
1805  mouseHoverProc = mouseHoverCallback.getAddress ();
1806  if (mouseHoverProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
1807
1808  caretCallback = new Callback(this, "caretProc", 1);
1809  caretProc = caretCallback.getAddress();
1810  if (caretProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
1811
1812  menuPositionCallback = new Callback(this, "menuPositionProc", 5);
1813  menuPositionProc = menuPositionCallback.getAddress();
1814  if (menuPositionProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
1815
1816  shellMapCallback = new Callback(this, "shellMapProc", 3);
1817  shellMapProc = shellMapCallback.getAddress();
1818  if (shellMapProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
1819  
1820  treeSelectionCallback = new Callback(this, "treeSelectionProc", 4);
1821  treeSelectionProc = treeSelectionCallback.getAddress();
1822  if (treeSelectionProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
1823  
1824  textCellDataCallback = new Callback (this, "textCellDataProc", 5);
1825  textCellDataProc = textCellDataCallback.getAddress ();
1826  if (textCellDataProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
1827  
1828  pixbufCellDataCallback = new Callback (this, "pixbufCellDataProc", 5);
1829  pixbufCellDataProc = pixbufCellDataCallback.getAddress ();
1830  if (pixbufCellDataProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
1831
1832  checkIfEventCallback = new Callback (this, "checkIfEventProc", 3);
1833  checkIfEventProc = checkIfEventCallback.getAddress ();
1834  if (checkIfEventProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
1835
1836  filterCallback = new Callback (this, "filterProc", 3);
1837  filterProc = filterCallback.getAddress ();
1838  if (filterProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
1839}
1840
1841void initializeWidgetTable () {
1842  indexTable = new int [GROW_SIZE];
1843  widgetTable = new Widget [GROW_SIZE];
1844  for (int i=0; i<GROW_SIZE-1; i++) indexTable [i] = i + 1;
1845  indexTable [GROW_SIZE - 1] = -1;
1846}
1847
1848/**   
1849 * Invokes platform specific functionality to dispose a GC handle.
1850 * <p>
1851 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
1852 * API for <code>Display</code>. It is marked public only so that it
1853 * can be shared within the packages provided by SWT. It is not
1854 * available on all platforms, and should never be called from
1855 * application code.
1856 * </p>
1857 *
1858 * @param hDC the platform specific GC handle
1859 * @param data the platform specific GC data 
1860 */
1861public void internal_dispose_GC (long /*int*/ gdkGC, GCData data) {
1862  OS.g_object_unref (gdkGC);
1863}
1864
1865/**   
1866 * Invokes platform specific functionality to allocate a new GC handle.
1867 * <p>
1868 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
1869 * API for <code>Display</code>. It is marked public only so that it
1870 * can be shared within the packages provided by SWT. It is not
1871 * available on all platforms, and should never be called from
1872 * application code.
1873 * </p>
1874 *
1875 * @param data the platform specific GC data 
1876 * @return the platform specific GC handle
1877 * 
1878 * @exception SWTError <ul>
1879 *    <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
1880 * </ul>
1881 * @exception SWTException <ul>
1882 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1883 * </ul>
1884 */
1885public long /*int*/ internal_new_GC (GCData data) {
1886  if (isDisposed()) SWT.error(SWT.ERROR_DEVICE_DISPOSED);
1887  long /*int*/ root = OS.GDK_ROOT_PARENT ();
1888  long /*int*/ gdkGC = OS.gdk_gc_new (root);
1889  if (gdkGC == 0) SWT.error (SWT.ERROR_NO_HANDLES);
1890  if (data != null) {
1891    int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
1892    if ((data.style & mask) == 0) {
1893      data.style |= SWT.LEFT_TO_RIGHT;
1894    }
1895    data.device = this;
1896    data.drawable = root;
1897    data.font = defaultFont;
1898  }
1899  return gdkGC;
1900}
1901
1902boolean isValidThread () {
1903  return thread == Thread.currentThread ();
1904}
1905
1906/**
1907 * Maps a point from one coordinate system to another.
1908 * When the control is null, coordinates are mapped to
1909 * the display.
1910 * <p>
1911 * NOTE: On right-to-left platforms where the coordinate
1912 * systems are mirrored, special care needs to be taken
1913 * when mapping coordinates from one control to another
1914 * to ensure the result is correctly mirrored.
1915 * 
1916 * Mapping a point that is the origin of a rectangle and
1917 * then adding the width and height is not equivalent to
1918 * mapping the rectangle.  When one control is mirrored
1919 * and the other is not, adding the width and height to a
1920 * point that was mapped causes the rectangle to extend
1921 * in the wrong direction.  Mapping the entire rectangle
1922 * instead of just one point causes both the origin and
1923 * the corner of the rectangle to be mapped.
1924 * </p>
1925 * 
1926 * @param from the source <code>Control</code> or <code>null</code>
1927 * @param to the destination <code>Control</code> or <code>null</code>
1928 * @param point to be mapped 
1929 * @return point with mapped coordinates 
1930 * 
1931 * @exception IllegalArgumentException <ul>
1932 *    <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
1933 *    <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li> 
1934 * </ul>
1935 * @exception SWTException <ul>
1936 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1937 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1938 * </ul>
1939 * 
1940 * @since 2.1.2
1941 */
1942public Point map (Control from, Control to, Point point) {
1943  checkDevice ();
1944  if (point == null) error (SWT.ERROR_NULL_ARGUMENT);  
1945  return map (from, to, point.x, point.y);
1946}
1947
1948/**
1949 * Maps a point from one coordinate system to another.
1950 * When the control is null, coordinates are mapped to
1951 * the display.
1952 * <p>
1953 * NOTE: On right-to-left platforms where the coordinate
1954 * systems are mirrored, special care needs to be taken
1955 * when mapping coordinates from one control to another
1956 * to ensure the result is correctly mirrored.
1957 * 
1958 * Mapping a point that is the origin of a rectangle and
1959 * then adding the width and height is not equivalent to
1960 * mapping the rectangle.  When one control is mirrored
1961 * and the other is not, adding the width and height to a
1962 * point that was mapped causes the rectangle to extend
1963 * in the wrong direction.  Mapping the entire rectangle
1964 * instead of just one point causes both the origin and
1965 * the corner of the rectangle to be mapped.
1966 * </p>
1967 * 
1968 * @param from the source <code>Control</code> or <code>null</code>
1969 * @param to the destination <code>Control</code> or <code>null</code>
1970 * @param x coordinates to be mapped
1971 * @param y coordinates to be mapped
1972 * @return point with mapped coordinates
1973 * 
1974 * @exception IllegalArgumentException <ul>
1975 *    <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li> 
1976 * </ul>
1977 * @exception SWTException <ul>
1978 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1979 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1980 * </ul>
1981 * 
1982 * @since 2.1.2
1983 */
1984public Point map (Control from, Control to, int x, int y) {
1985  checkDevice ();
1986  if (from != null && from.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
1987  if (to != null && to.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
1988  Point point = new Point (x, y);
1989  if (from != null) {
1990    long /*int*/ eventHandle = from.eventHandle ();
1991    OS.gtk_widget_realize (eventHandle);
1992    long /*int*/ window = OS.GTK_WIDGET_WINDOW (eventHandle);
1993    int [] origin_x = new int [1], origin_y = new int [1];
1994    OS.gdk_window_get_origin (window, origin_x, origin_y);
1995    point.x += origin_x [0];
1996    point.y += origin_y [0];
1997  }
1998  if (to != null) {
1999    long /*int*/ eventHandle = to.eventHandle ();
2000    OS.gtk_widget_realize (eventHandle);
2001    long /*int*/ window = OS.GTK_WIDGET_WINDOW (eventHandle);
2002    int [] origin_x = new int [1], origin_y = new int [1];
2003    OS.gdk_window_get_origin (window, origin_x, origin_y);
2004    point.x -= origin_x [0];
2005    point.y -= origin_y [0];
2006  }
2007  return point;
2008}
2009
2010/**
2011 * Maps a point from one coordinate system to another.
2012 * When the control is null, coordinates are mapped to
2013 * the display.
2014 * <p>
2015 * NOTE: On right-to-left platforms where the coordinate
2016 * systems are mirrored, special care needs to be taken
2017 * when mapping coordinates from one control to another
2018 * to ensure the result is correctly mirrored.
2019 * 
2020 * Mapping a point that is the origin of a rectangle and
2021 * then adding the width and height is not equivalent to
2022 * mapping the rectangle.  When one control is mirrored
2023 * and the other is not, adding the width and height to a
2024 * point that was mapped causes the rectangle to extend
2025 * in the wrong direction.  Mapping the entire rectangle
2026 * instead of just one point causes both the origin and
2027 * the corner of the rectangle to be mapped.
2028 * </p>
2029 * 
2030 * @param from the source <code>Control</code> or <code>null</code>
2031 * @param to the destination <code>Control</code> or <code>null</code>
2032 * @param rectangle to be mapped
2033 * @return rectangle with mapped coordinates
2034 * 
2035 * @exception IllegalArgumentException <ul>
2036 *    <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
2037 *    <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li> 
2038 * </ul>
2039 * @exception SWTException <ul>
2040 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2041 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2042 * </ul>
2043 * 
2044 * @since 2.1.2
2045 */
2046public Rectangle map (Control from, Control to, Rectangle rectangle) {
2047  checkDevice();
2048  if (rectangle == null) error (SWT.ERROR_NULL_ARGUMENT);
2049  return map (from, to, rectangle.x, rectangle.y, rectangle.width, rectangle.height);
2050}
2051
2052static char mbcsToWcs (char ch) {
2053  int key = ch & 0xFFFF;
2054  if (key <= 0x7F) return ch;
2055  byte [] buffer;
2056  if (key <= 0xFF) {
2057    buffer = new byte [1];
2058    buffer [0] = (byte) key;
2059  } else {
2060    buffer = new byte [2];
2061    buffer [0] = (byte) ((key >> 8) & 0xFF);
2062    buffer [1] = (byte) (key & 0xFF);
2063  }
2064  char [] result = Converter.mbcsToWcs (null, buffer);
2065  if (result.length == 0) return 0;
2066  return result [0];
2067}
2068
2069long /*int*/ menuPositionProc (long /*int*/ menu, long /*int*/ x, long /*int*/ y, long /*int*/ push_in, long /*int*/ user_data) {
2070  Widget widget = getWidget (menu);
2071  if (widget == null) return 0;
2072  return widget.menuPositionProc (menu, x, y, push_in, user_data);  
2073}
2074
2075/**
2076 * Maps a point from one coordinate system to another.
2077 * When the control is null, coordinates are mapped to
2078 * the display.
2079 * <p>
2080 * NOTE: On right-to-left platforms where the coordinate
2081 * systems are mirrored, special care needs to be taken
2082 * when mapping coordinates from one control to another
2083 * to ensure the result is correctly mirrored.
2084 * 
2085 * Mapping a point that is the origin of a rectangle and
2086 * then adding the width and height is not equivalent to
2087 * mapping the rectangle.  When one control is mirrored
2088 * and the other is not, adding the width and height to a
2089 * point that was mapped causes the rectangle to extend
2090 * in the wrong direction.  Mapping the entire rectangle
2091 * instead of just one point causes both the origin and
2092 * the corner of the rectangle to be mapped.
2093 * </p>
2094 * 
2095 * @param from the source <code>Control</code> or <code>null</code>
2096 * @param to the destination <code>Control</code> or <code>null</code>
2097 * @param x coordinates to be mapped
2098 * @param y coordinates to be mapped
2099 * @param width coordinates to be mapped
2100 * @param height coordinates to be mapped
2101 * @return rectangle with mapped coordinates
2102 * 
2103 * @exception IllegalArgumentException <ul>
2104 *    <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li> 
2105 * </ul>
2106 * @exception SWTException <ul>
2107 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2108 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2109 * </ul>
2110 * 
2111 * @since 2.1.2
2112 */
2113public Rectangle map (Control from, Control to, int x, int y, int width, int height) {
2114  checkDevice();
2115  if (from != null && from.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
2116  if (to != null && to.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
2117  Rectangle rect = new Rectangle (x, y, width, height);
2118  if (from != null) {
2119    long /*int*/ eventHandle = from.eventHandle ();
2120    OS.gtk_widget_realize (eventHandle);
2121    long /*int*/ window = OS.GTK_WIDGET_WINDOW (eventHandle);
2122    int [] origin_x = new int [1], origin_y = new int [1];
2123    OS.gdk_window_get_origin (window, origin_x, origin_y);
2124    rect.x += origin_x [0];
2125    rect.y += origin_y [0];
2126  }
2127  if (to != null) {
2128    long /*int*/ eventHandle = to.eventHandle ();
2129    OS.gtk_widget_realize (eventHandle);
2130    long /*int*/ window = OS.GTK_WIDGET_WINDOW (eventHandle);
2131    int [] origin_x = new int [1], origin_y = new int [1];
2132    OS.gdk_window_get_origin (window, origin_x, origin_y);
2133    rect.x -= origin_x [0];
2134    rect.y -= origin_y [0];
2135  }
2136  return rect;
2137}
2138
2139long /*int*/ mouseHoverProc (long /*int*/ handle) {
2140  Widget widget = getWidget (handle);
2141  if (widget == null) return 0;
2142  return widget.hoverProc (handle);
2143}
2144
2145/**
2146 * Generate a low level system event.
2147 * 
2148 * <code>post</code> is used to generate low level keyboard
2149 * and mouse events. The intent is to enable automated UI
2150 * testing by simulating the input from the user.  Most
2151 * SWT applications should never need to call this method.
2152 * 
2153 * <p>
2154 * <b>Event Types:</b>
2155 * <p>KeyDown, KeyUp
2156 * <p>The following fields in the <code>Event</code> apply:
2157 * <ul>
2158 * <li>(in) type KeyDown or KeyUp</li>
2159 * <p> Either one of:
2160 * <li>(in) character a character that corresponds to a keyboard key</li>
2161 * <li>(in) keyCode the key code of the key that was typed,
2162 *          as defined by the key code constants in class <code>SWT</code></li>
2163 * </ul>
2164 * <p>MouseDown, MouseUp</p>
2165 * <p>The following fields in the <code>Event</code> apply:
2166 * <ul>
2167 * <li>(in) type MouseDown or MouseUp
2168 * <li>(in) button the button that is pressed or released
2169 * </ul>
2170 * <p>MouseMove</p>
2171 * <p>The following fields in the <code>Event</code> apply:
2172 * <ul>
2173 * <li>(in) type MouseMove
2174 * <li>(in) x the x coordinate to move the mouse pointer to in screen coordinates
2175 * <li>(in) y the y coordinate to move the mouse pointer to in screen coordinates
2176 * </ul>
2177 * </dl>
2178 * 
2179 * @param event the event to be generated
2180 * 
2181 * @return true if the event was generated or false otherwise
2182 * 
2183 * @exception IllegalArgumentException <ul>
2184 *    <li>ERROR_NULL_ARGUMENT - if the event is null</li>
2185 * </ul>
2186 * @exception SWTException <ul>
2187 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2188 * </ul>
2189 *
2190 * @since 3.0
2191 * 
2192 */
2193public boolean post (Event event) {
2194  if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
2195  if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
2196  if (!OS.GDK_WINDOWING_X11()) return false;
2197  long /*int*/ xDisplay = OS.GDK_DISPLAY ();
2198  int type = event.type;
2199  switch (type) {
2200    case SWT.KeyDown:
2201    case SWT.KeyUp: {
2202      int keyCode = 0;
2203      long /*int*/ keysym = untranslateKey (event.keyCode);
2204      if (keysym != 0) keyCode = OS.XKeysymToKeycode (xDisplay, keysym);
2205      if (keyCode == 0) {
2206        char key = event.character;
2207        switch (key) {
2208          case '\r': keysym = OS.GDK_Return; break;
2209          default: keysym = wcsToMbcs (key);
2210        }
2211        keyCode = OS.XKeysymToKeycode (xDisplay, keysym);
2212        if (keyCode == 0) return false;
2213      }
2214      OS.XTestFakeKeyEvent (xDisplay, keyCode, type == SWT.KeyDown, 0);
2215      return true;
2216    }
2217    case SWT.MouseDown:
2218    case SWT.MouseMove: 
2219    case SWT.MouseUp: {
2220      if (type == SWT.MouseMove) {
2221        OS.XTestFakeMotionEvent (xDisplay, -1, event.x, event.y, 0);
2222      } else {
2223        int button = event.button;
2224        if (button < 1 || button > 3) return false;
2225        OS.XTestFakeButtonEvent (xDisplay, button, type == SWT.MouseDown, 0);
2226      }
2227      return true;
2228    }
2229  }
2230  return false;
2231}
2232
2233void postEvent (Event event) {
2234  /*
2235  * Place the event at the end of the event queue.
2236  * This code is always called in the Display's
2237  * thread so it must be re-enterant but does not
2238  * need to be synchronized.
2239  */
2240  if (eventQueue == null) eventQueue = new Event [4];
2241  int index = 0;
2242  int length = eventQueue.length;
2243  while (index < length) {
2244    if (eventQueue [index] == null) break;
2245    index++;
2246  }
2247  if (index == length) {
2248    Event [] newQueue = new Event [length + 4];
2249    System.arraycopy (eventQueue, 0, newQueue, 0, length);
2250    eventQueue = newQueue;
2251  }
2252  eventQueue [index] = event;
2253}
2254
2255void putGdkEvents () {
2256  if (gdkEventCount != 0) {
2257    for (int i = 0; i < gdkEventCount; i++) {
2258      if (gdkEventWidgets [i] == null || !gdkEventWidgets [i].isDisposed ()) {
2259        OS.gdk_event_put (gdkEvents [i]);
2260        OS.gdk_event_free (gdkEvents [i]);
2261      }
2262    }
2263    gdkEvents = null;
2264    gdkEventWidgets = null;
2265    gdkEventCount = 0;
2266  }
2267}
2268
2269/**
2270 * Reads an event from the operating system's event queue,
2271 * dispatches it appropriately, and returns <code>true</code>
2272 * if there is potentially more work to do, or <code>false</code>
2273 * if the caller can sleep until another event is placed on
2274 * the event queue.
2275 * <p>
2276 * In addition to checking the system event queue, this method also
2277 * checks if any inter-thread messages (created by <code>syncExec()</code>
2278 * or <code>asyncExec()</code>) are waiting to be processed, and if
2279 * so handles them before returning.
2280 * </p>
2281 *
2282 * @return <code>false</code> if the caller can sleep upon return from this method
2283 *
2284 * @exception SWTException <ul>
2285 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2286 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2287 * </ul>
2288 *
2289 * @see #sleep
2290 * @see #wake
2291 */
2292public boolean readAndDispatch () {
2293  checkDevice ();
2294  runPopups ();
2295  int status = OS.gtk_events_pending ();
2296  if (status != 0) {
2297    OS.gtk_main_iteration ();
2298    runDeferredEvents ();
2299    return true;
2300  }
2301  return runAsyncMessages ();
2302}
2303
2304synchronized void register () {
2305  for (int i=0; i<Displays.length; i++) {
2306    if (Displays [i] == null) {
2307      Displays [i] = this;
2308      return;
2309    }
2310  }
2311  Display [] newDisplays = new Display [Displays.length + 4];
2312  System.arraycopy (Displays, 0, newDisplays, 0, Displays.length);
2313  newDisplays [Displays.length] = this;
2314  Displays = newDisplays;
2315}
2316
2317/**
2318 * Releases any internal resources back to the operating
2319 * system and clears all fields except the device handle.
2320 * <p>
2321 * Disposes all shells which are currently open on the display. 
2322 * After this method has been invoked, all related related shells
2323 * will answer <code>true</code> when sent the message
2324 * <code>isDisposed()</code>.
2325 * </p><p>
2326 * When a device is destroyed, resources that were acquired
2327 * on behalf of the programmer need to be returned to the
2328 * operating system.  For example, if the device allocated a
2329 * font to be used as the system font, this font would be
2330 * freed in <code>release</code>.  Also,to assist the garbage
2331 * collector and minimize the amount of memory that is not
2332 * reclaimed when the programmer keeps a reference to a
2333 * disposed device, all fields except the handle are zero'd.
2334 * The handle is needed by <code>destroy</code>.
2335 * </p>
2336 * This method is called before <code>destroy</code>.
2337 * 
2338 * @see #dispose
2339 * @see #destroy
2340 */
2341protected void release () {
2342  sendEvent (SWT.Dispose, new Event ());
2343  Shell [] shells = getShells ();
2344  for (int i=0; i<shells.length; i++) {
2345    Shell shell = shells [i];
2346    if (!shell.isDisposed ())  shell.dispose ();
2347  }
2348  if (tray != null) tray.dispose ();
2349  tray = null;
2350  while (readAndDispatch ()) {}
2351  if (disposeList != null) {
2352    for (int i=0; i<disposeList.length; i++) {
2353      if (disposeList [i] != null) disposeList [i].run ();
2354    }
2355  }
2356  disposeList = null;
2357  synchronizer.releaseSynchronizer ();
2358  synchronizer = null;
2359  releaseDisplay ();
2360  super.release ();
2361}
2362
2363void releaseDisplay () {
2364  windowCallback2.dispose ();  windowCallback2 = null;
2365  windowCallback3.dispose ();  windowCallback3 = null;
2366  windowCallback4.dispose ();  windowCallback4 = null;
2367  windowCallback5.dispose ();  windowCallback5 = null;
2368  
2369  /* Dispose xfilter callback */
2370  filterCallback.dispose(); filterCallback = null;
2371  filterProc = 0;
2372
2373  /* Dispose checkIfEvent callback */
2374  checkIfEventCallback.dispose(); checkIfEventCallback = null;
2375  checkIfEventProc = 0;
2376  
2377  /* Dispose preedit window */
2378  if (preeditWindow != 0) OS.gtk_widget_destroy (preeditWindow);
2379  imControl = null;
2380
2381  /* Dispose the menu callback */
2382  menuPositionCallback.dispose (); menuPositionCallback = null;
2383  menuPositionProc = 0;
2384
2385  /* Dispose the shell map callback */
2386  shellMapCallback.dispose (); shellMapCallback = null;
2387  shellMapProc = 0;
2388  
2389  /* Dispose GtkTreeView callbacks */
2390  treeSelectionCallback.dispose (); treeSelectionCallback = null;
2391  treeSelectionProc = 0;
2392  textCellDataCallback.dispose (); textCellDataCallback = null;
2393  textCellDataProc = 0;
2394  pixbufCellDataCallback.dispose (); pixbufCellDataCallback = null;
2395  pixbufCellDataProc = 0;
2396
2397  /* Dispose the caret callback */
2398  if (caretId != 0) OS.gtk_timeout_remove (caretId);
2399  caretId = 0;
2400  caretProc = 0;
2401  caretCallback.dispose ();
2402  caretCallback = null;
2403  
2404  /* Dispose the timer callback */
2405  if (timerIds != null) {
2406    for (int i=0; i<timerIds.length; i++) {
2407      if (timerIds [i] != 0) OS.gtk_timeout_remove (timerIds [i]);
2408    }
2409  }
2410  timerIds = null;
2411  timerList = null;
2412  timerProc = 0;
2413  timerCallback.dispose ();
2414  timerCallback = null;
2415  windowTimerProc = 0;
2416  windowTimerCallback.dispose ();
2417  windowTimerCallback = null;
2418  
2419  /* Dispose mouse hover callback */
2420  if (mouseHoverId != 0) OS.gtk_timeout_remove (mouseHoverId);
2421  mouseHoverId = 0;
2422  mouseHoverHandle = mouseHoverProc = 0;
2423  mouseHoverCallback.dispose ();
2424  mouseHoverCallback = null;
2425
2426  thread = null;
2427  windowProc2 = windowProc3 = windowProc4 = windowProc5 = 0;
2428  
2429  /* Dispose the default font */
2430  if (defaultFont != 0) OS.pango_font_description_free (defaultFont);
2431  defaultFont = 0;
2432  
2433  /* Dispose the System Images */
2434  if (errorPixmap != 0) {
2435    OS.g_object_unref (errorPixmap);
2436    OS.g_object_unref (errorMask);
2437  }
2438  if (infoPixmap != 0) {
2439    OS.g_object_unref (infoPixmap);
2440    OS.g_object_unref (infoMask);
2441  }
2442  if (questionPixmap != 0) {
2443    OS.g_object_unref (questionPixmap);
2444    OS.g_object_unref (questionMask);
2445  }
2446  if (warningPixmap != 0) {
2447    OS.g_object_unref (warningPixmap);
2448    OS.g_object_unref (warningMask);
2449  }
2450  errorPixmap = infoPixmap = questionPixmap = warningPixmap = 0;
2451  errorMask = infoMask = questionMask = warningMask = 0;
2452  
2453  /* Release the System Cursors */
2454  for (int i = 0; i < cursors.length; i++) {
2455    if (cursors [i] != null) cursors [i].dispose ();
2456  }
2457  cursors = null;
2458
2459  COLOR_WIDGET_DARK_SHADOW = COLOR_WIDGET_NORMAL_SHADOW = COLOR_WIDGET_LIGHT_SHADOW =
2460  COLOR_WIDGET_HIGHLIGHT_SHADOW = COLOR_WIDGET_BACKGROUND = COLOR_WIDGET_BORDER =
2461  COLOR_LIST_FOREGROUND = COLOR_LIST_BACKGROUND = COLOR_LIST_SELECTION = COLOR_LIST_SELECTION_TEXT =
2462  COLOR_INFO_BACKGROUND = null;
2463  
2464  /* Dispose the event callback */
2465  OS.gdk_event_handler_set (0, 0, 0);
2466  eventCallback.dispose ();  eventCallback = null;
2467}
2468
2469/**
2470 * Removes the listener from the collection of listeners who will
2471 * be notifed when an event of the given type occurs anywhere in
2472 * this display.
2473 *
2474 * @param eventType the type of event to listen for
2475 * @param listener the listener which should no longer be notified when the event occurs
2476 *
2477 * @exception IllegalArgumentException <ul>
2478 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2479 * </ul>
2480 * @exception SWTException <ul>
2481 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2482 * </ul>
2483 *
2484 * @see Listener
2485 * @see #addFilter
2486 * @see #addListener
2487 * 
2488 * @since 3.0
2489 */
2490public void removeFilter (int eventType, Listener listener) {
2491  checkDevice ();
2492  if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
2493  if (filterTable == null) return;
2494  filterTable.unhook (eventType, listener);
2495  if (filterTable.size () == 0) filterTable = null;
2496}
2497
2498long /*int*/ removeGdkEvent () {
2499  if (gdkEventCount == 0) return 0;
2500  long /*int*/ event = gdkEvents [0];
2501  --gdkEventCount;
2502  System.arraycopy (gdkEvents, 1, gdkEvents, 0, gdkEventCount);
2503  System.arraycopy (gdkEventWidgets, 1, gdkEventWidgets, 0, gdkEventCount);
2504  gdkEvents [gdkEventCount] = 0;
2505  gdkEventWidgets [gdkEventCount] = null;
2506  if (gdkEventCount == 0) {
2507    gdkEvents = null;
2508    gdkEventWidgets = null;
2509  }
2510  return event;
2511}
2512
2513/**
2514 * Removes the listener from the collection of listeners who will
2515 * be notifed when an event of the given type occurs.
2516 *
2517 * @param eventType the type of event to listen for
2518 * @param listener the listener which should no longer be notified when the event occurs
2519 *
2520 * @exception IllegalArgumentException <ul>
2521 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2522 * </ul>
2523 * @exception SWTException <ul>
2524 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2525 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2526 * </ul>
2527 *
2528 * @see Listener
2529 * @see #addListener
2530 * 
2531 * @since 2.0 
2532 */
2533public void removeListener (int eventType, Listener listener) {
2534  checkDevice ();
2535  if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
2536  if (eventTable == null) return;
2537  eventTable.unhook (eventType, listener);
2538}
2539
2540void removeMouseHoverTimeout (long /*int*/ handle) {
2541  if (handle != mouseHoverHandle) return;
2542  if (mouseHoverId != 0) OS.gtk_timeout_remove (mouseHoverId);
2543  mouseHoverId = 0;
2544  mouseHoverHandle = 0;
2545}
2546
2547void removePopup (Menu menu) {
2548  if (popups == null) return;
2549  for (int i=0; i<popups.length; i++) {
2550    if (popups [i] == menu) {
2551      popups [i] = null;
2552      return;
2553    }
2554  }
2555}
2556
2557Widget removeWidget (long /*int*/ handle) {
2558  if (handle == 0) return null;
2559  Widget widget = null;
2560  int index = (int)/*64*/ OS.g_object_get_qdata (handle, SWT_OBJECT_INDEX) - 1;
2561  if (0 <= index && index < widgetTable.length) {
2562    widget = widgetTable [index];
2563    widgetTable [index] = null;
2564    indexTable [index] = freeSlot;
2565    freeSlot = index;
2566    OS.g_object_set_qdata (handle, SWT_OBJECT_INDEX, 0);
2567  }
2568  return widget;  
2569}
2570
2571boolean runAsyncMessages () {
2572  return synchronizer.runAsyncMessages ();
2573}
2574
2575boolean runDeferredEvents () {
2576  /*
2577  * Run deferred events.  This code is always
2578  * called in the Display's thread so it must
2579  * be re-enterant but need not be synchronized.
2580  */
2581  while (eventQueue != null) {
2582    
2583    /* Take an event off the queue */
2584    Event event = eventQueue [0];
2585    if (event == null) break;
2586    int length = eventQueue.length;
2587    System.arraycopy (eventQueue, 1, eventQueue, 0, --length);
2588    eventQueue [length] = null;
2589
2590    /* Run the event */
2591    Widget widget = event.widget;
2592    if (widget != null && !widget.isDisposed ()) {
2593      Widget item = event.item;
2594      if (item == null || !item.isDisposed ()) {
2595        widget.sendEvent (event);
2596      }
2597    }
2598
2599    /*
2600    * At this point, the event queue could
2601    * be null due to a recursive invokation
2602    * when running the event.
2603    */
2604  }
2605
2606  /* Clear the queue */
2607  eventQueue = null;
2608  return true;
2609}
2610
2611boolean runPopups () {
2612  if (popups == null) return false;
2613  boolean result = false;
2614  while (popups != null) {
2615    Menu menu = popups [0];
2616    if (menu == null) break;
2617    int length = popups.length;
2618    System.arraycopy (popups, 1, popups, 0, --length);
2619    popups [length] = null;
2620    runDeferredEvents ();
2621    menu._setVisible (true);
2622    result = true;
2623  }
2624  popups = null;
2625  return result;
2626}
2627
2628/**
2629 * On platforms which support it, sets the application name
2630 * to be the argument. On Motif, for example, this can be used
2631 * to set the name used for resource lookup.
2632 *
2633 * @param name the new app name
2634 */
2635public static void setAppName (String name) {
2636  APP_NAME = name;
2637}
2638
2639/**
2640 * Sets the location of the on-screen pointer relative to the top left corner
2641 * of the screen.  <b>Note: It is typically considered bad practice for a
2642 * program to move the on-screen pointer location.</b>
2643 *
2644 * @param x the new x coordinate for the cursor
2645 * @param y the new y coordinate for the cursor
2646 * 
2647 * @exception SWTException <ul>
2648 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2649 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2650 * </ul>
2651 * 
2652 * @since 2.1
2653 */
2654public void setCursorLocation (int x, int y) {
2655  checkDevice ();
2656  /* This is not supported on GTK */
2657}
2658
2659/**
2660 * Sets the location of the on-screen pointer relative to the top left corner
2661 * of the screen.  <b>Note: It is typically considered bad practice for a
2662 * program to move the on-screen pointer location.</b>
2663 *
2664 * @param point new position
2665 * 
2666 * @exception SWTException <ul>
2667 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2668 *    <li>ERROR_NULL_ARGUMENT - if the point is null
2669 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2670 * </ul>
2671 * 
2672 * @since 2.0
2673 */
2674public void setCursorLocation (Point point) {
2675  checkDevice ();
2676  if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
2677  setCursorLocation (point.x, point.y);
2678}
2679
2680/**
2681 * Sets the application defined property of the receiver
2682 * with the specified name to the given argument.
2683 * <p>
2684 * Applications may have associated arbitrary objects with the
2685 * receiver in this fashion. If the objects stored in the
2686 * properties need to be notified when the display is disposed
2687 * of, it is the application's responsibility provide a
2688 * <code>disposeExec()</code> handler which does so.
2689 * </p>
2690 *
2691 * @param key the name of the property
2692 * @param value the new value for the property
2693 *
2694 * @exception IllegalArgumentException <ul>
2695 *    <li>ERROR_NULL_ARGUMENT - if the key is null</li>
2696 * </ul>
2697 * @exception SWTException <ul>
2698 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2699 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2700 * </ul>
2701 *
2702 * @see #setData
2703 * @see #disposeExec
2704 */
2705public void setData (String key, Object value) {
2706  checkDevice ();
2707  if (key == null) error (SWT.ERROR_NULL_ARGUMENT);
2708
2709  if (key.equals (DISPATCH_EVENT_KEY)) {
2710    if (value == null || value instanceof int []) {
2711      dispatchEvents = (int []) value;
2712      if (value == null) putGdkEvents ();
2713      return;
2714    }
2715  }
2716
2717  /* Remove the key/value pair */
2718  if (value == null) {
2719    if (keys == null) return;
2720    int index = 0;
2721    while (index < keys.length && !keys [index].equals (key)) index++;
2722    if (index == keys.length) return;
2723    if (keys.length == 1) {
2724      keys = null;
2725      values = null;
2726    } else {
2727      String [] newKeys = new String [keys.length - 1];
2728      Object [] newValues = new Object [values.length - 1];
2729      System.arraycopy (keys, 0, newKeys, 0, index);
2730      System.arraycopy (keys, index + 1, newKeys, index, newKeys.length - index);
2731      System.arraycopy (values, 0, newValues, 0, index);
2732      System.arraycopy (values, index + 1, newValues, index, newValues.length - index);
2733      keys = newKeys;
2734      values = newValues;
2735    }
2736    return;
2737  }
2738  
2739  /* Add the key/value pair */
2740  if (keys == null) {
2741    keys = new String [] {key};
2742    values = new Object [] {value};
2743    return;
2744  }
2745  for (int i=0; i<keys.length; i++) {
2746    if (keys [i].equals (key)) {
2747      values [i] = value;
2748      return;
2749    }
2750  }
2751  String [] newKeys = new String [keys.length + 1];
2752  Object [] newValues = new Object [values.length + 1];
2753  System.arraycopy (keys, 0, newKeys, 0, keys.length);
2754  System.arraycopy (values, 0, newValues, 0, values.length);
2755  newKeys [keys.length] = key;
2756  newValues [values.length] = value;
2757  keys = newKeys;
2758  values = newValues;
2759}
2760
2761/**
2762 * Sets the application defined, display specific data
2763 * associated with the receiver, to the argument.
2764 * The <em>display specific data</em> is a single,
2765 * unnamed field that is stored with every display. 
2766 * <p>
2767 * Applications may put arbitrary objects in this field. If
2768 * the object stored in the display specific data needs to
2769 * be notified when the display is disposed of, it is the
2770 * application's responsibility provide a
2771 * <code>disposeExec()</code> handler which does so.
2772 * </p>
2773 *
2774 * @param data the new display specific data
2775 *
2776 * @exception SWTException <ul>
2777 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2778 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2779 * </ul>
2780 *
2781 * @see #getData
2782 * @see #disposeExec
2783 */
2784public void setData (Object data) {
2785  checkDevice ();
2786  this.data = data;
2787}
2788
2789/**
2790 * Sets the synchronizer used by the display to be
2791 * the argument, which can not be null.
2792 *
2793 * @param synchronizer the new synchronizer for the display (must not be null)
2794 *
2795 * @exception IllegalArgumentException <ul>
2796 *    <li>ERROR_NULL_ARGUMENT - if the synchronizer is null</li>
2797 * </ul>
2798 * @exception SWTException <ul>
2799 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2800 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2801 * </ul>
2802 */
2803public void setSynchronizer (Synchronizer synchronizer) {
2804  checkDevice ();
2805  if (synchronizer == null) error (SWT.ERROR_NULL_ARGUMENT);
2806  if (this.synchronizer != null) {
2807    this.synchronizer.runAsyncMessages();
2808  }
2809  this.synchronizer = synchronizer;
2810}
2811
2812void showIMWindow (Control control) {
2813  imControl = control;
2814  if (preeditWindow == 0) { 
2815    preeditWindow = OS.gtk_window_new (OS.GTK_WINDOW_POPUP);
2816    if (preeditWindow == 0) error (SWT.ERROR_NO_HANDLES);
2817    preeditLabel = OS.gtk_label_new (null);
2818    if (preeditLabel == 0) error (SWT.ERROR_NO_HANDLES);
2819    OS.gtk_container_add (preeditWindow, preeditLabel);
2820    OS.gtk_widget_show (preeditLabel);
2821  }
2822  long /*int*/ [] preeditString = new long /*int*/ [1];
2823  long /*int*/ [] pangoAttrs = new long /*int*/ [1];
2824  long /*int*/ imHandle = control.imHandle ();
2825  OS.gtk_im_context_get_preedit_string (imHandle, preeditString, pangoAttrs, null);
2826  if (preeditString [0] != 0 && OS.strlen (preeditString [0]) > 0) {
2827    OS.gtk_widget_modify_bg (preeditWindow,  OS.GTK_STATE_NORMAL, control.getBackgroundColor ());
2828    OS.gtk_widget_modify_fg (preeditLabel,  OS.GTK_STATE_NORMAL, control.getForegroundColor ());    
2829    OS.gtk_widget_modify_font (preeditLabel, control.getFontDescription ());
2830    if (pangoAttrs [0] != 0) OS.gtk_label_set_attributes (preeditLabel, pangoAttrs[0]);
2831    OS.gtk_label_set_text (preeditLabel, preeditString [0]);
2832    Point point = control.toDisplay (control.getIMCaretPos ());
2833    OS.gtk_window_move (preeditWindow, point.x, point.y);    
2834    GtkRequisition requisition = new GtkRequisition ();
2835    OS.gtk_widget_size_request (preeditLabel, requisition);
2836    OS.gtk_window_resize (preeditWindow, requisition.width, requisition.height);
2837    OS.gtk_widget_show (preeditWindow);
2838  } else {
2839    OS.gtk_widget_hide (preeditWindow);
2840  }    
2841  if (preeditString [0] != 0) OS.g_free (preeditString [0]);
2842  if (pangoAttrs [0] != 0) OS.pango_attr_list_unref (pangoAttrs [0]);  
2843}
2844
2845/**
2846 * Causes the user-interface thread to <em>sleep</em> (that is,
2847 * to be put in a state where it does not consume CPU cycles)
2848 * until an event is received or it is otherwise awakened.
2849 *
2850 * @return <code>true</code> if an event requiring dispatching was placed on the queue.
2851 *
2852 * @exception SWTException <ul>
2853 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2854 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2855 * </ul>
2856 *
2857 * @see #wake
2858 */
2859public boolean sleep () {
2860  checkDevice ();
2861  //TODO need to sleep waiting for the next event
2862  do {
2863    if (getMessageCount () != 0) break;
2864    if (OS.gtk_events_pending () != 0) break;
2865    try {
2866      synchronized (OS_LOCK) {
2867        OS_LOCK.wait (50);
2868      }
2869    } catch (Exception e) {
2870      return false;
2871    }
2872  } while (!wake);
2873  wake = false;
2874  return true;
2875}
2876
2877/**
2878 * Causes the <code>run()</code> method of the runnable to
2879 * be invoked by the user-interface thread after the specified
2880 * number of milliseconds have elapsed. If milliseconds is less
2881 * than zero, the runnable is not executed.
2882 *
2883 * @param milliseconds the delay before running the runnable
2884 * @param runnable code to run on the user-interface thread
2885 *
2886 * @exception IllegalArgumentException <ul>
2887 *    <li>ERROR_NULL_ARGUMENT - if the runnable is null</li>
2888 * </ul>
2889 * @exception SWTException <ul>
2890 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2891 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2892 * </ul>
2893 *
2894 * @see #asyncExec
2895 */
2896public void timerExec (int milliseconds, Runnable runnable) {
2897  checkDevice ();
2898  if (runnable == null) error (SWT.ERROR_NULL_ARGUMENT);
2899  if (timerList == null) timerList = new Runnable [4];
2900  if (timerIds == null) timerIds = new int [4];  
2901  int index = 0;
2902  while (index < timerList.length) {
2903    if (timerList [index] == runnable) break;
2904    index++;
2905  }
2906  if (index != timerList.length) {
2907    OS.gtk_timeout_remove (timerIds [index]);
2908    timerList [index] = null;
2909    timerIds [index] = 0;
2910    if (milliseconds < 0) return;
2911  } else {
2912    if (milliseconds < 0) return;
2913    index = 0;
2914    while (index < timerList.length) {
2915      if (timerList [index] == null) break;
2916      index++;
2917    }
2918    if (index == timerList.length) {
2919      Runnable [] newTimerList = new Runnable [timerList.length + 4];
2920      System.arraycopy (timerList, 0, newTimerList, 0, timerList.length);
2921      timerList = newTimerList;
2922      int [] newTimerIds = new int [timerIds.length + 4];
2923      System.arraycopy (timerIds, 0, newTimerIds, 0, timerIds.length);
2924      timerIds = newTimerIds;
2925    }
2926  }
2927  int timerId = OS.gtk_timeout_add (milliseconds, timerProc, index);
2928  if (timerId != 0) {
2929    timerIds [index] = timerId;
2930    timerList [index] = runnable;
2931  }
2932}
2933
2934long /*int*/ timerProc (long /*int*/ i) {
2935  if (timerList == null) return 0;
2936  int index = (int)/*64*/i;
2937  if (0 <= index && index < timerList.length) {
2938    Runnable runnable = timerList [index];
2939    timerList [index] = null;
2940    timerIds [index] = 0;
2941    if (runnable != null) runnable.run ();
2942  }
2943  return 0;
2944}
2945
2946long /*int*/ caretProc (long /*int*/ clientData) {
2947  caretId = 0;
2948  if (currentCaret == null) {
2949    return 0;
2950  }
2951  if (currentCaret.blinkCaret()) {
2952    int blinkRate = currentCaret.blinkRate;
2953    caretId = OS.gtk_timeout_add (blinkRate, caretProc, 0);
2954  } else {
2955    currentCaret = null;
2956  }
2957  return 0;
2958}
2959
2960long /*int*/ pixbufCellDataProc (long /*int*/ tree_column, long /*int*/ cell, long /*int*/ tree_model, long /*int*/ iter, long /*int*/ data) {
2961  Widget widget = getWidget (data);
2962  if (widget == null) return 0;
2963  return widget.pixbufCellDataProc (tree_column, cell, tree_model, iter, data);
2964}
2965long /*int*/ textCellDataProc (long /*int*/ tree_column, long /*int*/ cell, long /*int*/ tree_model, long /*int*/ iter, long /*int*/ data) {
2966  Widget widget = getWidget (data);
2967  if (widget == null) return 0;
2968  return widget.textCellDataProc (tree_column, cell, tree_model, iter, data);
2969}
2970
2971long /*int*/ treeSelectionProc (long /*int*/ model, long /*int*/ path, long /*int*/ iter, long /*int*/ data) {
2972  Widget widget = getWidget (data);
2973  if (widget == null) return 0;
2974  return widget.treeSelectionProc (model, path, iter, treeSelection, treeSelectionLength++);
2975}
2976
2977void sendEvent (int eventType, Event event) {
2978  if (eventTable == null && filterTable == null) {
2979    return;
2980  }
2981  if (event == null) event = new Event ();
2982  event.display = this;
2983  event.type = eventType;
2984  if (event.time == 0) event.time = getLastEventTime ();
2985  if (!filterEvent (event)) {
2986    if (eventTable != null) eventTable.sendEvent (event);
2987  }
2988}
2989
2990void setCurrentCaret (Caret caret) {
2991  if (caretId != 0) OS.gtk_timeout_remove(caretId);
2992  caretId = 0;
2993  currentCaret = caret;
2994  if (caret == null) return;
2995  int blinkRate = currentCaret.blinkRate;
2996  caretId = OS.gtk_timeout_add (blinkRate, caretProc, 0); 
2997}
2998
2999long /*int*/ shellMapProc (long /*int*/ handle, long /*int*/ arg0, long /*int*/ user_data) {
3000  Widget widget = getWidget (handle);
3001  if (widget == null) return 0;
3002  return widget.shellMapProc (handle, arg0, user_data);
3003}
3004
3005/**
3006 * Causes the <code>run()</code> method of the runnable to
3007 * be invoked by the user-interface thread at the next 
3008 * reasonable opportunity. The thread which calls this method
3009 * is suspended until the runnable completes.
3010 *
3011 * @param runnable code to run on the user-interface thread.
3012 *
3013 * @exception SWTException <ul>
3014 *    <li>ERROR_FAILED_EXEC - if an exception occured when executing the runnable</li>
3015 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3016 * </ul>
3017 *
3018 * @see #asyncExec
3019 */
3020public void syncExec (Runnable runnable) {
3021  if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
3022  synchronizer.syncExec (runnable);
3023}
3024
3025static int translateKey (int key) {
3026  for (int i=0; i<KeyTable.length; i++) {
3027    if (KeyTable [i] [0] == key) return KeyTable [i] [1];
3028  }
3029  return 0;
3030}
3031
3032static int untranslateKey (int key) {
3033  for (int i=0; i<KeyTable.length; i++) {
3034    if (KeyTable [i] [1] == key) return KeyTable [i] [0];
3035  }
3036  return 0;
3037}
3038
3039/**
3040 * Forces all outstanding paint requests for the display
3041 * to be processed before this method returns.
3042 *
3043 * @exception SWTException <ul>
3044 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3045 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3046 * </ul>
3047 * 
3048 * @see Control#update
3049 */
3050public void update () {
3051  checkDevice ();
3052  flushExposes (0, true);
3053  OS.gdk_window_process_all_updates ();
3054}
3055
3056/**
3057 * If the receiver's user-interface thread was <code>sleep</code>'ing, 
3058 * causes it to be awakened and start running again. Note that this
3059 * method may be called from any thread.
3060 * 
3061 * @exception SWTException <ul>
3062 *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3063 * </ul>
3064 * 
3065 * @see #sleep
3066 */
3067public void wake () {
3068  if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
3069  if (thread == Thread.currentThread ()) return;
3070  wakeThread ();
3071}
3072
3073void wakeThread () {
3074  wake = true;
3075  // NOT IMPLEMENTED - need to wake up the event loop
3076}
3077
3078static char wcsToMbcs (char ch) {
3079  int key = ch & 0xFFFF;
3080  if (key <= 0x7F) return ch;
3081  byte [] buffer = Converter.wcsToMbcs (null, new char [] {ch}, false);
3082  if (buffer.length == 1) return (char) buffer [0];
3083  if (buffer.length == 2) {
3084    return (char) (((buffer [0] & 0xFF) << 8) | (buffer [1] & 0xFF));
3085  }
3086  return 0;
3087}
3088
3089long /*int*/ windowProc (long /*int*/ handle, long /*int*/ user_data) {
3090  Widget widget = getWidget (handle);
3091  if (widget == null) return 0;
3092  return widget.windowProc (handle, user_data);
3093}
3094
3095long /*int*/ windowProc (long /*int*/ handle, long /*int*/ arg0, long /*int*/ user_data) {
3096  Widget widget = getWidget (handle);
3097  if (widget == null) return 0;
3098  return widget.windowProc (handle, arg0, user_data);
3099}
3100
3101long /*int*/ windowProc (long /*int*/ handle, long /*int*/ arg0, long /*int*/ arg1, long /*int*/ user_data) {
3102  Widget widget = getWidget (handle);
3103  if (widget == null) return 0;
3104  return widget.windowProc (handle, arg0, arg1, user_data);
3105}
3106
3107long /*int*/ windowProc (long /*int*/ handle, long /*int*/ arg0, long /*int*/ arg1, long /*int*/ arg2, long /*int*/ user_data) {
3108  Widget widget = getWidget (handle);
3109  if (widget == null) return 0;
3110  return widget.windowProc (handle, arg0, arg1, arg2, user_data);
3111}
3112
3113long /*int*/ windowTimerProc (long /*int*/ handle) {
3114  Widget widget = getWidget (handle);
3115  if (widget == null) return 0;
3116  return widget.timerProc (handle);
3117}
3118
3119}