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}