25
|
1 /*******************************************************************************
|
|
2 * Copyright (c) 2000, 2008 IBM Corporation and others.
|
|
3 * All rights reserved. This program and the accompanying materials
|
|
4 * are made available under the terms of the Eclipse Public License v1.0
|
|
5 * which accompanies this distribution, and is available at
|
|
6 * http://www.eclipse.org/legal/epl-v10.html
|
|
7 *
|
|
8 * Contributors:
|
|
9 * IBM Corporation - initial API and implementation
|
|
10 * Port to the D programming language:
|
|
11 * Frank Benoit <benoit@tionex.de>
|
|
12 *******************************************************************************/
|
|
13 module org.eclipse.swt.widgets.Display;
|
|
14
|
|
15 import org.eclipse.swt.SWT;
|
|
16 import org.eclipse.swt.graphics.Color;
|
|
17 import org.eclipse.swt.graphics.Cursor;
|
|
18 import org.eclipse.swt.graphics.Device;
|
|
19 import org.eclipse.swt.graphics.DeviceData;
|
|
20 import org.eclipse.swt.graphics.Font;
|
|
21 import org.eclipse.swt.graphics.GCData;
|
|
22 import org.eclipse.swt.graphics.Image;
|
|
23 import org.eclipse.swt.graphics.ImageData;
|
|
24 import org.eclipse.swt.graphics.PaletteData;
|
|
25 import org.eclipse.swt.graphics.Point;
|
|
26 import org.eclipse.swt.graphics.Rectangle;
|
|
27 import org.eclipse.swt.graphics.Resource;
|
|
28 import org.eclipse.swt.internal.Compatibility;
|
|
29 import org.eclipse.swt.internal.Converter;
|
|
30 import org.eclipse.swt.internal.Lock;
|
|
31 import org.eclipse.swt.internal.LONG;
|
|
32 import org.eclipse.swt.internal.gtk.OS;
|
|
33 import org.eclipse.swt.widgets.Caret;
|
|
34 import org.eclipse.swt.widgets.Control;
|
|
35 import org.eclipse.swt.widgets.Dialog;
|
|
36 import org.eclipse.swt.widgets.Event;
|
|
37 import org.eclipse.swt.widgets.EventTable;
|
|
38 import org.eclipse.swt.widgets.Listener;
|
|
39 import org.eclipse.swt.widgets.Menu;
|
|
40 import org.eclipse.swt.widgets.Monitor;
|
|
41 import org.eclipse.swt.widgets.Shell;
|
|
42 import org.eclipse.swt.widgets.Synchronizer;
|
|
43 import org.eclipse.swt.widgets.Tray;
|
|
44 import org.eclipse.swt.widgets.Widget;
|
|
45
|
|
46 import tango.stdc.string;
|
|
47 import java.lang.all;
|
|
48
|
|
49 import tango.core.Thread;
|
|
50
|
|
51 /**
|
|
52 * Instances of this class are responsible for managing the
|
|
53 * connection between SWT and the underlying operating
|
|
54 * system. Their most important function is to implement
|
|
55 * the SWT event loop in terms of the platform event model.
|
|
56 * They also provide various methods for accessing information
|
|
57 * about the operating system, and have overall control over
|
|
58 * the operating system resources which SWT allocates.
|
|
59 * <p>
|
|
60 * Applications which are built with SWT will <em>almost always</em>
|
|
61 * require only a single display. In particular, some platforms
|
|
62 * which SWT supports will not allow more than one <em>active</em>
|
|
63 * display. In other words, some platforms do not support
|
|
64 * creating a new display if one already exists that has not been
|
|
65 * sent the <code>dispose()</code> message.
|
|
66 * <p>
|
|
67 * In SWT, the thread which creates a <code>Display</code>
|
|
68 * instance is distinguished as the <em>user-interface thread</em>
|
|
69 * for that display.
|
|
70 * </p>
|
|
71 * The user-interface thread for a particular display has the
|
|
72 * following special attributes:
|
|
73 * <ul>
|
|
74 * <li>
|
|
75 * The event loop for that display must be run from the thread.
|
|
76 * </li>
|
|
77 * <li>
|
|
78 * Some SWT API methods (notably, most of the public methods in
|
|
79 * <code>Widget</code> and its subclasses), may only be called
|
|
80 * from the thread. (To support multi-threaded user-interface
|
|
81 * applications, class <code>Display</code> provides inter-thread
|
|
82 * communication methods which allow threads other than the
|
|
83 * user-interface thread to request that it perform operations
|
|
84 * on their behalf.)
|
|
85 * </li>
|
|
86 * <li>
|
|
87 * The thread is not allowed to construct other
|
|
88 * <code>Display</code>s until that display has been disposed.
|
|
89 * (Note that, this is in addition to the restriction mentioned
|
|
90 * above concerning platform support for multiple displays. Thus,
|
|
91 * the only way to have multiple simultaneously active displays,
|
|
92 * even on platforms which support it, is to have multiple threads.)
|
|
93 * </li>
|
|
94 * </ul>
|
|
95 * Enforcing these attributes allows SWT to be implemented directly
|
|
96 * on the underlying operating system's event model. This has
|
|
97 * numerous benefits including smaller footprint, better use of
|
|
98 * resources, safer memory management, clearer program logic,
|
|
99 * better performance, and fewer overall operating system threads
|
|
100 * required. The down side however, is that care must be taken
|
|
101 * (only) when constructing multi-threaded applications to use the
|
|
102 * inter-thread communication mechanisms which this class provides
|
|
103 * when required.
|
|
104 * </p><p>
|
|
105 * All SWT API methods which may only be called from the user-interface
|
|
106 * thread are distinguished in their documentation by indicating that
|
|
107 * they throw the "<code>ERROR_THREAD_INVALID_ACCESS</code>"
|
|
108 * SWT exception.
|
|
109 * </p>
|
|
110 * <dl>
|
|
111 * <dt><b>Styles:</b></dt>
|
|
112 * <dd>(none)</dd>
|
|
113 * <dt><b>Events:</b></dt>
|
|
114 * <dd>Close, Dispose, Settings</dd>
|
|
115 * </dl>
|
|
116 * <p>
|
|
117 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
|
|
118 * </p>
|
|
119 * @see #syncExec
|
|
120 * @see #asyncExec
|
|
121 * @see #wake
|
|
122 * @see #readAndDispatch
|
|
123 * @see #sleep
|
|
124 * @see Device#dispose
|
|
125 * @see <a href="http://www.eclipse.org/swt/snippets/#display">Display snippets</a>
|
|
126 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
|
|
127 */
|
|
128 public class Display : Device {
|
|
129
|
|
130 /* Events Dispatching and Callback */
|
|
131 int gdkEventCount;
|
|
132 GdkEvent* [] gdkEvents;
|
|
133 Widget [] gdkEventWidgets;
|
|
134 int [] dispatchEvents;
|
|
135 Event [] eventQueue;
|
|
136 GPollFD[] fds;
|
|
137 int allocated_nfds;
|
|
138 bool wake_state;
|
|
139 int max_priority, timeout;
|
|
140 void*/*Callback*/ eventCallback, filterCallback;
|
|
141
|
|
142 CallbackData*[int] windowProcCallbackDatas; // to prevent GC from collect
|
|
143
|
|
144 CallbackData filterProcCallbackData;
|
|
145 EventTable eventTable, filterTable;
|
|
146 static String APP_NAME = "SWT"; //$NON-NLS-1$
|
|
147 static const String DISPATCH_EVENT_KEY = "org.eclipse.swt.internal.gtk.dispatchEvent";
|
|
148 static const String ADD_WIDGET_KEY = "org.eclipse.swt.internal.addWidget";
|
|
149 GClosure*[] closures;
|
|
150 int [] signalIds;
|
|
151
|
|
152 /* Widget Table */
|
|
153 int [] indexTable;
|
|
154 int freeSlot;
|
|
155 GtkWidget* lastHandle;
|
|
156 Widget lastWidget;
|
|
157 Widget [] widgetTable;
|
|
158 const static int GROW_SIZE = 1024;
|
|
159 static int SWT_OBJECT_INDEX;
|
|
160 static int SWT_OBJECT_INDEX1;
|
|
161 static int SWT_OBJECT_INDEX2;
|
|
162
|
|
163 /* Modality */
|
|
164 Shell [] modalShells;
|
|
165 Dialog modalDialog;
|
|
166 static final String GET_MODAL_DIALOG = "org.eclipse.swt.internal.gtk.getModalDialog"; //$NON-NLS-1$
|
|
167 static final String SET_MODAL_DIALOG = "org.eclipse.swt.internal.gtk.setModalDialog"; //$NON-NLS-1$
|
|
168
|
|
169 /* Focus */
|
|
170 int focusEvent;
|
|
171 Control focusControl;
|
|
172 Shell activeShell;
|
|
173 bool activePending;
|
|
174 bool ignoreActivate, ignoreFocus;
|
|
175
|
|
176 /* Input method resources */
|
|
177 Control imControl;
|
|
178 GtkWindow* preeditWindow;
|
|
179 GtkLabel* preeditLabel;
|
|
180
|
|
181 /* Sync/Async Widget Communication */
|
|
182 Synchronizer synchronizer;
|
|
183 Thread thread;
|
|
184
|
|
185 /* Display Shutdown */
|
|
186 Runnable [] disposeList;
|
|
187
|
|
188 /* System Tray */
|
|
189 Tray tray;
|
|
190
|
|
191 /* Timers */
|
|
192 int [] timerIds;
|
|
193 Runnable [] timerList;
|
|
194 CallbackData timerProcCallbackData;
|
|
195
|
|
196 /* Caret */
|
|
197 Caret currentCaret;
|
|
198 int caretId;
|
|
199 CallbackData caretProcCallbackData;
|
|
200
|
|
201 /* Mnemonics */
|
|
202 Control mnemonicControl;
|
|
203
|
|
204 /* Mouse hover */
|
|
205 int mouseHoverId;
|
|
206 GtkWidget* mouseHoverHandle;
|
|
207 CallbackData mouseHoverProcCallbackData;
|
|
208
|
|
209 /* Menu position callback */
|
|
210
|
|
211 /* Tooltip size allocate callback */
|
|
212
|
|
213 /* Shell map callback */
|
|
214 CallbackData shellMapProcCallbackData;
|
|
215 GClosure* shellMapProcClosure;
|
|
216
|
|
217 /* Idle proc callback */
|
|
218 CallbackData idleProcCallbackData;
|
|
219 int idleHandle;
|
|
220 static const String ADD_IDLE_PROC_KEY = "org.eclipse.swt.internal.gtk.addIdleProc";
|
|
221 static const String REMOVE_IDLE_PROC_KEY = "org.eclipse.swt.internal.gtk.removeIdleProc";
|
|
222 Object idleLock;
|
|
223 bool idleNeeded;
|
|
224
|
|
225 /* GtkTreeView callbacks */
|
|
226 int[] treeSelection;
|
|
227 int treeSelectionLength;
|
|
228
|
|
229 /* Set direction callback */
|
|
230 CallbackData setDirectionProcCallbackData;
|
|
231 static const String GET_DIRECTION_PROC_KEY = "org.eclipse.swt.internal.gtk.getDirectionProc"; //$NON-NLS-1$
|
|
232
|
|
233 /* Set emissionProc callback */
|
|
234 CallbackData emissionProcCallbackData;
|
|
235 static const String GET_EMISSION_PROC_KEY = "org.eclipse.swt.internal.gtk.getEmissionProc"; //$NON-NLS-1$
|
|
236
|
|
237 /* Get all children callback */
|
|
238 CallbackData allChildrenProcCallbackData;
|
|
239 GList* allChildren;
|
|
240
|
|
241 CallbackData cellDataProcCallbackData;
|
|
242
|
|
243 /* Settings callbacks */
|
|
244 GtkWidget* shellHandle;
|
|
245 bool settingsChanged, runSettingsFld;
|
|
246 CallbackData styleSetProcCallbackData;
|
|
247
|
|
248 /* Entry focus behaviour */
|
|
249 bool entrySelectOnFocus;
|
|
250
|
|
251 /* Enter/Exit events */
|
|
252 Control currentControl;
|
|
253
|
|
254 /* Flush exposes */
|
|
255 int /*long*/ checkIfEventProc;
|
|
256 void*/*Callback*/ checkIfEventCallback;
|
|
257 GdkWindow* flushWindow;
|
|
258 bool flushAll;
|
|
259 GdkRectangle* flushRect;
|
|
260 XExposeEvent* exposeEvent;
|
|
261 XVisibilityEvent* visibilityEvent;
|
|
262 //int /*long*/ [] flushData = new int /*long*/ [1];
|
|
263
|
|
264 /* System Resources */
|
|
265 Font systemFont;
|
|
266 Image errorImage, infoImage, questionImage, warningImage;
|
|
267 Cursor [] cursors;
|
|
268 Resource [] resources;
|
|
269 static const int RESOURCE_SIZE = 1 + 4 + SWT.CURSOR_HAND + 1;
|
|
270
|
|
271 /* Colors */
|
|
272 GdkColor* COLOR_WIDGET_DARK_SHADOW, COLOR_WIDGET_NORMAL_SHADOW, COLOR_WIDGET_LIGHT_SHADOW;
|
|
273 GdkColor* COLOR_WIDGET_HIGHLIGHT_SHADOW, COLOR_WIDGET_BACKGROUND, COLOR_WIDGET_FOREGROUND, COLOR_WIDGET_BORDER;
|
|
274 GdkColor* COLOR_LIST_FOREGROUND, COLOR_LIST_BACKGROUND, COLOR_LIST_SELECTION, COLOR_LIST_SELECTION_TEXT;
|
|
275 GdkColor* COLOR_INFO_BACKGROUND, COLOR_INFO_FOREGROUND;
|
|
276 GdkColor* COLOR_TITLE_FOREGROUND, COLOR_TITLE_BACKGROUND, COLOR_TITLE_BACKGROUND_GRADIENT;
|
|
277 GdkColor* COLOR_TITLE_INACTIVE_FOREGROUND, COLOR_TITLE_INACTIVE_BACKGROUND, COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT;
|
|
278
|
|
279 /* Popup Menus */
|
|
280 Menu [] popups;
|
|
281
|
|
282 /* Click count*/
|
|
283 int clickCount = 1;
|
|
284
|
|
285 /* Timestamp of the Last Received Events */
|
|
286 int lastEventTime, lastUserEventTime;
|
|
287
|
|
288 /* Fixed Subclass */
|
|
289 static int /*long*/ fixed_type;
|
|
290 static int /*long*/ fixed_info_ptr;
|
|
291 static extern(C) void function(GtkWidget* handle, GtkAllocation* allocation) oldFixedSizeAllocateProc;
|
|
292
|
|
293
|
|
294 /* Renderer Subclass */
|
|
295 static int /*long*/ text_renderer_type, pixbuf_renderer_type, toggle_renderer_type;
|
|
296 static int /*long*/ text_renderer_info_ptr, pixbuf_renderer_info_ptr, toggle_renderer_info_ptr;
|
|
297
|
|
298 /* Key Mappings */
|
|
299 static const int [] [] KeyTable = [
|
|
300
|
|
301 /* Keyboard and Mouse Masks */
|
|
302 [OS.GDK_Alt_L, SWT.ALT],
|
|
303 [OS.GDK_Alt_R, SWT.ALT],
|
|
304 [OS.GDK_Meta_L, SWT.ALT],
|
|
305 [OS.GDK_Meta_R, SWT.ALT],
|
|
306 [OS.GDK_Shift_L, SWT.SHIFT],
|
|
307 [OS.GDK_Shift_R, SWT.SHIFT],
|
|
308 [OS.GDK_Control_L, SWT.CONTROL],
|
|
309 [OS.GDK_Control_R, SWT.CONTROL],
|
|
310 // [OS.GDK_????, SWT.COMMAND],
|
|
311 // [OS.GDK_????, SWT.COMMAND],
|
|
312
|
|
313 /* Non-Numeric Keypad Keys */
|
|
314 [OS.GDK_Up, SWT.ARROW_UP],
|
|
315 [OS.GDK_KP_Up, SWT.ARROW_UP],
|
|
316 [OS.GDK_Down, SWT.ARROW_DOWN],
|
|
317 [OS.GDK_KP_Down, SWT.ARROW_DOWN],
|
|
318 [OS.GDK_Left, SWT.ARROW_LEFT],
|
|
319 [OS.GDK_KP_Left, SWT.ARROW_LEFT],
|
|
320 [OS.GDK_Right, SWT.ARROW_RIGHT],
|
|
321 [OS.GDK_KP_Right, SWT.ARROW_RIGHT],
|
|
322 [OS.GDK_Page_Up, SWT.PAGE_UP],
|
|
323 [OS.GDK_KP_Page_Up, SWT.PAGE_UP],
|
|
324 [OS.GDK_Page_Down, SWT.PAGE_DOWN],
|
|
325 [OS.GDK_KP_Page_Down, SWT.PAGE_DOWN],
|
|
326 [OS.GDK_Home, SWT.HOME],
|
|
327 [OS.GDK_KP_Home, SWT.HOME],
|
|
328 [OS.GDK_End, SWT.END],
|
|
329 [OS.GDK_KP_End, SWT.END],
|
|
330 [OS.GDK_Insert, SWT.INSERT],
|
|
331 [OS.GDK_KP_Insert, SWT.INSERT],
|
|
332
|
|
333 /* Virtual and Ascii Keys */
|
|
334 [OS.GDK_BackSpace, SWT.BS],
|
|
335 [OS.GDK_Return, SWT.CR],
|
|
336 [OS.GDK_Delete, SWT.DEL],
|
|
337 [OS.GDK_KP_Delete, SWT.DEL],
|
|
338 [OS.GDK_Escape, SWT.ESC],
|
|
339 [OS.GDK_Linefeed, SWT.LF],
|
|
340 [OS.GDK_Tab, SWT.TAB],
|
|
341 [OS.GDK_ISO_Left_Tab, SWT.TAB],
|
|
342
|
|
343 /* Functions Keys */
|
|
344 [OS.GDK_F1, SWT.F1],
|
|
345 [OS.GDK_F2, SWT.F2],
|
|
346 [OS.GDK_F3, SWT.F3],
|
|
347 [OS.GDK_F4, SWT.F4],
|
|
348 [OS.GDK_F5, SWT.F5],
|
|
349 [OS.GDK_F6, SWT.F6],
|
|
350 [OS.GDK_F7, SWT.F7],
|
|
351 [OS.GDK_F8, SWT.F8],
|
|
352 [OS.GDK_F9, SWT.F9],
|
|
353 [OS.GDK_F10, SWT.F10],
|
|
354 [OS.GDK_F11, SWT.F11],
|
|
355 [OS.GDK_F12, SWT.F12],
|
|
356 [OS.GDK_F13, SWT.F13],
|
|
357 [OS.GDK_F14, SWT.F14],
|
|
358 [OS.GDK_F15, SWT.F15],
|
|
359
|
|
360 /* Numeric Keypad Keys */
|
|
361 [OS.GDK_KP_Multiply, SWT.KEYPAD_MULTIPLY],
|
|
362 [OS.GDK_KP_Add, SWT.KEYPAD_ADD],
|
|
363 [OS.GDK_KP_Enter, SWT.KEYPAD_CR],
|
|
364 [OS.GDK_KP_Subtract, SWT.KEYPAD_SUBTRACT],
|
|
365 [OS.GDK_KP_Decimal, SWT.KEYPAD_DECIMAL],
|
|
366 [OS.GDK_KP_Divide, SWT.KEYPAD_DIVIDE],
|
|
367 [OS.GDK_KP_0, SWT.KEYPAD_0],
|
|
368 [OS.GDK_KP_1, SWT.KEYPAD_1],
|
|
369 [OS.GDK_KP_2, SWT.KEYPAD_2],
|
|
370 [OS.GDK_KP_3, SWT.KEYPAD_3],
|
|
371 [OS.GDK_KP_4, SWT.KEYPAD_4],
|
|
372 [OS.GDK_KP_5, SWT.KEYPAD_5],
|
|
373 [OS.GDK_KP_6, SWT.KEYPAD_6],
|
|
374 [OS.GDK_KP_7, SWT.KEYPAD_7],
|
|
375 [OS.GDK_KP_8, SWT.KEYPAD_8],
|
|
376 [OS.GDK_KP_9, SWT.KEYPAD_9],
|
|
377 [OS.GDK_KP_Equal, SWT.KEYPAD_EQUAL],
|
|
378
|
|
379 /* Other keys */
|
|
380 [OS.GDK_Caps_Lock, SWT.CAPS_LOCK],
|
|
381 [OS.GDK_Num_Lock, SWT.NUM_LOCK],
|
|
382 [OS.GDK_Scroll_Lock, SWT.SCROLL_LOCK],
|
|
383 [OS.GDK_Pause, SWT.PAUSE],
|
|
384 [OS.GDK_Break, SWT.BREAK],
|
|
385 [OS.GDK_Print, SWT.PRINT_SCREEN],
|
|
386 [OS.GDK_Help, SWT.HELP],
|
|
387
|
|
388 ];
|
|
389
|
|
390 /* Multiple Displays. */
|
|
391 static Display Default;
|
|
392 static Display [] Displays;
|
|
393
|
|
394 /* Package name */
|
|
395 static const String PACKAGE_PREFIX = "org.eclipse.swt.widgets.";
|
|
396 /* This code is intentionally commented.
|
|
397 * ".class" can not be used on CLDC.
|
|
398 */
|
|
399 // static {
|
|
400 // String name = Display.class.getName ();
|
|
401 // int index = name.lastIndexOf ('.');
|
|
402 // PACKAGE_NAME = name.substring (0, index + 1);
|
|
403 // }
|
|
404
|
|
405 static this() {
|
|
406 Displays = new Display [4];
|
|
407 initDeviceFinder();
|
|
408 SWT_OBJECT_INDEX = OS.g_quark_from_string ("SWT_OBJECT_INDEX");
|
|
409 SWT_OBJECT_INDEX1 = OS.g_quark_from_string ("SWT_OBJECT_INDEX1");
|
|
410 SWT_OBJECT_INDEX2 = OS.g_quark_from_string ("SWT_OBJECT_INDEX2");
|
|
411 }
|
|
412
|
|
413 /* GTK Version */
|
|
414 static const int MAJOR = 2;
|
|
415 static const int MINOR = 0;
|
|
416 static const int MICRO = 6;
|
|
417
|
|
418 /* Display Data */
|
|
419 Object data;
|
|
420 String [] keys;
|
|
421 Object [] values;
|
|
422
|
|
423 /* Initial Guesses for Shell Trimmings. */
|
|
424 int borderTrimWidth = 4, borderTrimHeight = 4;
|
|
425 int resizeTrimWidth = 6, resizeTrimHeight = 6;
|
|
426 int titleBorderTrimWidth = 5, titleBorderTrimHeight = 28;
|
|
427 int titleResizeTrimWidth = 6, titleResizeTrimHeight = 29;
|
|
428 int titleTrimWidth = 0, titleTrimHeight = 23;
|
|
429 bool ignoreTrim;
|
|
430
|
|
431 /* Window Manager */
|
|
432 String windowManager;
|
|
433
|
|
434 /*
|
|
435 * TEMPORARY CODE. Install the runnable that
|
|
436 * gets the current display. This code will
|
|
437 * be removed in the future.
|
|
438 */
|
|
439 private static void initDeviceFinder(){
|
|
440 DeviceFinder = new class() Runnable {
|
|
441 public void run () {
|
|
442 Device device = getCurrent ();
|
|
443 if (device is null) {
|
|
444 device = getDefault ();
|
|
445 }
|
|
446 setDevice (device);
|
|
447 }
|
|
448 };
|
|
449 }
|
|
450
|
|
451 /*
|
|
452 * TEMPORARY CODE.
|
|
453 */
|
|
454 static void setDevice (Device device) {
|
|
455 CurrentDevice = device;
|
|
456 }
|
|
457
|
|
458 /**
|
|
459 * Constructs a new instance of this class.
|
|
460 * <p>
|
|
461 * Note: The resulting display is marked as the <em>current</em>
|
|
462 * display. If this is the first display which has been
|
|
463 * constructed since the application started, it is also
|
|
464 * marked as the <em>default</em> display.
|
|
465 * </p>
|
|
466 *
|
|
467 * @exception SWTException <ul>
|
|
468 * <li>ERROR_THREAD_INVALID_ACCESS - if called from a thread that already created an existing display</li>
|
|
469 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
|
|
470 * </ul>
|
|
471 *
|
|
472 * @see #getCurrent
|
|
473 * @see #getDefault
|
|
474 * @see Widget#checkSubclass
|
|
475 * @see Shell
|
|
476 */
|
|
477 public this () {
|
|
478 this (null);
|
|
479 }
|
|
480
|
|
481 /**
|
|
482 * Constructs a new instance of this class using the parameter.
|
|
483 *
|
|
484 * @param data the device data
|
|
485 */
|
|
486 public this (DeviceData data) {
|
|
487 super (data);
|
|
488 synchronizer = new Synchronizer (this);
|
|
489 idleLock = new Object();
|
|
490 flushRect = new GdkRectangle ();
|
|
491 exposeEvent = new XExposeEvent ();
|
|
492 visibilityEvent = new XVisibilityEvent ();
|
|
493 cursors = new Cursor [SWT.CURSOR_HAND + 1];
|
|
494 }
|
|
495
|
|
496 /**
|
|
497 * Adds the listener to the collection of listeners who will
|
|
498 * be notified when an event of the given type occurs anywhere
|
|
499 * in a widget. The event type is one of the event constants
|
|
500 * defined in class <code>SWT</code>. When the event does occur,
|
|
501 * the listener is notified by sending it the <code>handleEvent()</code>
|
|
502 * message.
|
|
503 * <p>
|
|
504 * Setting the type of an event to <code>SWT.None</code> from
|
|
505 * within the <code>handleEvent()</code> method can be used to
|
|
506 * change the event type and stop subsequent Java listeners
|
|
507 * from running. Because event filters run before other listeners,
|
|
508 * event filters can both block other listeners and set arbitrary
|
|
509 * fields within an event. For this reason, event filters are both
|
|
510 * powerful and dangerous. They should generally be avoided for
|
|
511 * performance, debugging and code maintenance reasons.
|
|
512 * </p>
|
|
513 *
|
|
514 * @param eventType the type of event to listen for
|
|
515 * @param listener the listener which should be notified when the event occurs
|
|
516 *
|
|
517 * @exception IllegalArgumentException <ul>
|
|
518 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
|
|
519 * </ul>
|
|
520 * @exception SWTException <ul>
|
|
521 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
522 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
523 * </ul>
|
|
524 *
|
|
525 * @see Listener
|
|
526 * @see SWT
|
|
527 * @see #removeFilter
|
|
528 * @see #removeListener
|
|
529 *
|
|
530 * @since 3.0
|
|
531 */
|
|
532 public void addFilter (int eventType, Listener listener) {
|
|
533 checkDevice ();
|
|
534 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
535 if (filterTable is null) filterTable = new EventTable ();
|
|
536 filterTable.hook (eventType, listener);
|
|
537 }
|
|
538
|
|
539 void addGdkEvent (GdkEvent* event) {
|
|
540 if (gdkEvents is null) {
|
|
541 int length = GROW_SIZE;
|
|
542 gdkEvents.length = length;
|
|
543 gdkEventWidgets.length = length;
|
|
544 gdkEventCount = 0;
|
|
545 }
|
|
546 if (gdkEventCount is gdkEvents.length) {
|
|
547 int length = gdkEventCount + GROW_SIZE;
|
|
548 GdkEvent* [] newEvents = new GdkEvent* [length];
|
|
549 SimpleType!(GdkEvent*).arraycopy (gdkEvents, 0, newEvents, 0, gdkEventCount);
|
|
550 gdkEvents = newEvents;
|
|
551 Widget [] newWidgets = new Widget [length];
|
|
552 System.arraycopy (gdkEventWidgets, 0, newWidgets, 0, gdkEventCount);
|
|
553 gdkEventWidgets = newWidgets;
|
|
554 }
|
|
555 Widget widget = null;
|
|
556 GtkWidget* handle = OS.gtk_get_event_widget (event);
|
|
557 if (handle !is null) {
|
|
558 do {
|
|
559 widget = getWidget (handle);
|
|
560 } while (widget is null && (handle = OS.gtk_widget_get_parent (handle)) !is null);
|
|
561 }
|
|
562 gdkEvents [gdkEventCount] = event;
|
|
563 gdkEventWidgets [gdkEventCount] = widget;
|
|
564 gdkEventCount++;
|
|
565 }
|
|
566
|
|
567 void addIdleProc() {
|
|
568 synchronized (idleLock){
|
|
569 this.idleNeeded = true;
|
|
570 if (idleHandle is 0) {
|
|
571 idleProcCallbackData.display = this;
|
|
572 idleProcCallbackData.data = null;
|
|
573 idleHandle = OS.g_idle_add ( &idleProcFunc, &idleProcCallbackData );
|
|
574 }
|
|
575 }
|
|
576 }
|
|
577
|
|
578 /**
|
|
579 * Adds the listener to the collection of listeners who will
|
|
580 * be notified when an event of the given type occurs. The event
|
|
581 * type is one of the event constants defined in class <code>SWT</code>.
|
|
582 * When the event does occur in the display, the listener is notified by
|
|
583 * sending it the <code>handleEvent()</code> message.
|
|
584 *
|
|
585 * @param eventType the type of event to listen for
|
|
586 * @param listener the listener which should be notified when the event occurs
|
|
587 *
|
|
588 * @exception IllegalArgumentException <ul>
|
|
589 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
|
|
590 * </ul>
|
|
591 * @exception SWTException <ul>
|
|
592 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
593 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
594 * </ul>
|
|
595 *
|
|
596 * @see Listener
|
|
597 * @see SWT
|
|
598 * @see #removeListener
|
|
599 *
|
|
600 * @since 2.0
|
|
601 */
|
|
602 public void addListener (int eventType, Listener listener) {
|
|
603 checkDevice ();
|
|
604 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
605 if (eventTable is null) eventTable = new EventTable ();
|
|
606 eventTable.hook (eventType, listener);
|
|
607 }
|
|
608
|
|
609 void allChildrenCollect( GtkWidget* widget, int recurse ){
|
|
610 allChildrenProcCallbackData.display = this;
|
|
611 allChildrenProcCallbackData.data = cast(void*)recurse;
|
|
612 OS.gtk_container_forall (cast(GtkContainer*)widget, cast(GtkCallback)&allChildrenProcFunc, &allChildrenProcCallbackData);
|
|
613 }
|
|
614 private static extern(C) int /*long*/ allChildrenProcFunc (GtkWidget* handle, void* user_data) {
|
|
615 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
616 CallbackData* cbdata = cast(CallbackData*)user_data;
|
|
617 return cbdata.display.allChildrenProc( cast(GtkWidget*)handle, cast(int)cbdata.data );
|
|
618 }
|
|
619 int /*long*/ allChildrenProc (GtkWidget* widget, int /*long*/ recurse) {
|
|
620 allChildren = OS.g_list_append (allChildren, widget);
|
|
621 if (recurse !is 0 && OS.GTK_IS_CONTAINER (cast(GTypeInstance*)widget)) {
|
|
622 allChildrenProcCallbackData.display = this;
|
|
623 allChildrenProcCallbackData.data = cast(void*)recurse;
|
|
624 OS.gtk_container_forall (cast(GtkContainer*)widget, cast(GtkCallback)&allChildrenProcFunc, &allChildrenProcCallbackData);
|
|
625 }
|
|
626 return 0;
|
|
627 }
|
|
628
|
|
629 void addMouseHoverTimeout (GtkWidget* handle) {
|
|
630 if (mouseHoverId !is 0) OS.gtk_timeout_remove (mouseHoverId);
|
|
631 mouseHoverProcCallbackData.display = this;
|
|
632 mouseHoverProcCallbackData.data = cast(void*)handle;
|
|
633 mouseHoverId = OS.gtk_timeout_add (400, &mouseHoverProcFunc, &mouseHoverProcCallbackData);
|
|
634 mouseHoverHandle = handle;
|
|
635 }
|
|
636
|
|
637 void addPopup (Menu menu) {
|
|
638 if (popups is null) popups = new Menu [4];
|
|
639 int length = popups.length;
|
|
640 for (int i=0; i<length; i++) {
|
|
641 if (popups [i] is menu) return;
|
|
642 }
|
|
643 int index = 0;
|
|
644 while (index < length) {
|
|
645 if (popups [index] is null) break;
|
|
646 index++;
|
|
647 }
|
|
648 if (index is length) {
|
|
649 Menu [] newPopups = new Menu [length + 4];
|
|
650 System.arraycopy (popups, 0, newPopups, 0, length);
|
|
651 popups = newPopups;
|
|
652 }
|
|
653 popups [index] = menu;
|
|
654 }
|
|
655
|
|
656 void addWidget (GtkWidget* handle, Widget widget) {
|
|
657 if (handle is null) return;
|
|
658 if (freeSlot is -1) {
|
|
659 int len = (freeSlot = indexTable.length) + GROW_SIZE;
|
|
660 int[] newIndexTable = new int[len];
|
|
661 Widget[] newWidgetTable = new Widget [len];
|
|
662 System.arraycopy (indexTable, 0, newIndexTable, 0, freeSlot);
|
|
663 System.arraycopy (widgetTable, 0, newWidgetTable, 0, freeSlot);
|
|
664 for (int i = freeSlot; i < len - 1; i++) {
|
|
665 newIndexTable[i] = i + 1;
|
|
666 }
|
|
667 newIndexTable[len - 1] = -1;
|
|
668 indexTable = newIndexTable;
|
|
669 widgetTable = newWidgetTable;
|
|
670 }
|
|
671 int index = freeSlot + 1;
|
|
672 OS.g_object_set_qdata (cast(GObject*)handle, SWT_OBJECT_INDEX, cast(void*)index);
|
|
673 int oldSlot = freeSlot;
|
|
674 freeSlot = indexTable[oldSlot];
|
|
675 indexTable [oldSlot] = -2;
|
|
676 widgetTable [oldSlot] = widget;
|
|
677 }
|
|
678
|
|
679 /**
|
|
680 * Causes the <code>run()</code> method of the runnable to
|
|
681 * be invoked by the user-interface thread at the next
|
|
682 * reasonable opportunity. The caller of this method continues
|
|
683 * to run in parallel, and is not notified when the
|
|
684 * runnable has completed. Specifying <code>null</code> as the
|
|
685 * runnable simply wakes the user-interface thread when run.
|
|
686 * <p>
|
|
687 * Note that at the time the runnable is invoked, widgets
|
|
688 * that have the receiver as their display may have been
|
|
689 * disposed. Therefore, it is necessary to check for this
|
|
690 * case inside the runnable before accessing the widget.
|
|
691 * </p>
|
|
692 *
|
|
693 * @param runnable code to run on the user-interface thread or <code>null</code>
|
|
694 *
|
|
695 * @exception SWTException <ul>
|
|
696 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
697 * </ul>
|
|
698 *
|
|
699 * @see #syncExec
|
|
700 */
|
|
701 public void asyncExec (Runnable runnable) {
|
|
702 synchronized (Device.classinfo) {
|
|
703 if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
|
|
704 synchronized (idleLock) {
|
|
705 if (idleNeeded && idleHandle is 0) {
|
|
706 //NOTE: calling unlocked function in OS
|
|
707 idleHandle = OS.g_idle_add (&idleProcFunc, cast(void*) this);
|
|
708 }
|
|
709 }
|
|
710 synchronizer.asyncExec (runnable);
|
|
711 }
|
|
712 }
|
|
713
|
|
714 /**
|
|
715 * Causes the system hardware to emit a short sound
|
|
716 * (if it supports this capability).
|
|
717 *
|
|
718 * @exception SWTException <ul>
|
|
719 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
720 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
721 * </ul>
|
|
722 */
|
|
723 public void beep () {
|
|
724 if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
|
|
725 OS.gdk_beep();
|
|
726 if (!OS.GDK_WINDOWING_X11 ()) {
|
|
727 OS.gdk_flush ();
|
|
728 } else {
|
|
729 void* xDisplay = OS.GDK_DISPLAY ();
|
|
730 OS.XFlush (xDisplay);
|
|
731 }
|
|
732 }
|
|
733
|
|
734 void doCellDataProc( GtkWidget* widget, GtkTreeViewColumn *tree_column, GtkCellRenderer *cell_renderer ){
|
|
735 cellDataProcCallbackData.display = this;
|
|
736 cellDataProcCallbackData.data = widget;
|
|
737 OS.gtk_tree_view_column_set_cell_data_func ( tree_column, cell_renderer, &cellDataProcFunc, &cellDataProcCallbackData, null );
|
|
738 }
|
|
739
|
|
740 private static extern(C) void cellDataProcFunc (
|
|
741 GtkTreeViewColumn *tree_column,
|
|
742 GtkCellRenderer *cell,
|
|
743 GtkTreeModel *tree_model,
|
|
744 GtkTreeIter *iter,
|
|
745 void* data)
|
|
746 {
|
|
747 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
748 CallbackData* cbdata = cast(CallbackData*)data;
|
|
749 return cbdata.display.cellDataProc( tree_column, cell, tree_model, iter, cbdata.data );
|
|
750 }
|
|
751
|
|
752 void cellDataProc(
|
|
753 GtkTreeViewColumn *tree_column,
|
|
754 GtkCellRenderer *cell,
|
|
755 GtkTreeModel *tree_model,
|
|
756 GtkTreeIter *iter,
|
|
757 void* data)
|
|
758 {
|
|
759 Widget widget = getWidget (cast(GtkWidget*)data);
|
|
760 if (widget is null) return;
|
|
761 widget.cellDataProc (tree_column, cell, tree_model, iter, data);
|
|
762 }
|
|
763
|
|
764 protected override void checkDevice () {
|
|
765 if (thread is null) error (SWT.ERROR_WIDGET_DISPOSED);
|
|
766 if (thread !is Thread.getThis ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
|
|
767 if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
|
|
768 }
|
|
769
|
|
770 static void checkDisplay (Thread thread, bool multiple) {
|
|
771 synchronized (Device.classinfo) {
|
|
772 for (int i=0; i<Displays.length; i++) {
|
|
773 if (Displays [i] !is null) {
|
|
774 if (!multiple) SWT.error (SWT.ERROR_NOT_IMPLEMENTED, null, " [multiple displays]"); //$NON-NLS-1$
|
|
775 if (Displays [i].thread is thread) SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS);
|
|
776 }
|
|
777 }
|
|
778 }
|
|
779 }
|
|
780
|
|
781 private static extern(C) int checkIfEventProcFunc (void* display, XEvent* xEvent, char* userData) {
|
|
782 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
783 auto disp = cast(Display)userData;
|
|
784 return disp.checkIfEventProcMeth( display, xEvent );
|
|
785 }
|
|
786
|
|
787 int checkIfEventProcMeth (void* display, XEvent* xEvent) {
|
|
788 int type = xEvent.type;
|
|
789 switch (type) {
|
|
790 case OS.VisibilityNotify:
|
|
791 case OS.Expose:
|
|
792 case OS.GraphicsExpose:
|
|
793 break;
|
|
794 default:
|
|
795 return 0;
|
|
796 }
|
|
797 GdkWindow* window = OS.gdk_window_lookup ( xEvent.xany.window );
|
|
798 if (window is null) return 0;
|
|
799 if (flushWindow !is null) {
|
|
800 if (flushAll) {
|
|
801 auto tempWindow = window;
|
|
802 do {
|
|
803 if (tempWindow is flushWindow) break;
|
|
804 } while ((tempWindow = OS.gdk_window_get_parent (tempWindow)) !is null);
|
|
805 if (tempWindow !is flushWindow) return 0;
|
|
806 } else {
|
|
807 if (window !is flushWindow) return 0;
|
|
808 }
|
|
809 }
|
|
810 *exposeEvent = *cast(XExposeEvent*)xEvent;
|
|
811 switch (type) {
|
|
812 case OS.Expose:
|
|
813 case OS.GraphicsExpose: {
|
|
814 flushRect.x = exposeEvent.x;
|
|
815 flushRect.y = exposeEvent.y;
|
|
816 flushRect.width = exposeEvent.width;
|
|
817 flushRect.height = exposeEvent.height;
|
|
818 OS.gdk_window_invalidate_rect (window, flushRect, true);
|
|
819 exposeEvent.type = -1;
|
|
820 memmove (xEvent, exposeEvent, XExposeEvent.sizeof);
|
|
821 break;
|
|
822 }
|
|
823 case OS.VisibilityNotify: {
|
|
824 memmove (visibilityEvent, xEvent, XVisibilityEvent.sizeof);
|
|
825 GtkWidget* handle;
|
|
826 OS.gdk_window_get_user_data (window, cast(void**) & handle);
|
|
827 Widget widget = handle !is null ? getWidget (handle) : null;
|
|
828 if (auto control = cast(Control)widget ) {
|
|
829 if (window is control.paintWindow ()) {
|
|
830 if (visibilityEvent.state is OS.VisibilityFullyObscured) {
|
|
831 control.state |= Widget.OBSCURED;
|
|
832 } else {
|
|
833 control.state &= ~Widget.OBSCURED;
|
|
834 }
|
|
835 }
|
|
836 }
|
|
837 break;
|
|
838 default:
|
|
839 }
|
|
840 }
|
|
841 return 0;
|
|
842 }
|
|
843
|
|
844 /**
|
|
845 * Checks that this class can be subclassed.
|
|
846 * <p>
|
|
847 * IMPORTANT: See the comment in <code>Widget.checkSubclass()</code>.
|
|
848 * </p>
|
|
849 *
|
|
850 * @exception SWTException <ul>
|
|
851 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
|
|
852 * </ul>
|
|
853 *
|
|
854 * @see Widget#checkSubclass
|
|
855 */
|
|
856 protected void checkSubclass () {
|
|
857 //PORTING_TODO if (!isValidClass (getClass ())) error (SWT.ERROR_INVALID_SUBCLASS);
|
|
858 }
|
|
859
|
|
860 void clearModal (Shell shell) {
|
|
861 if (modalShells is null) return;
|
|
862 int index = 0, length_ = modalShells.length;
|
|
863 while (index < length_) {
|
|
864 if (modalShells [index] is shell) break;
|
|
865 if (modalShells [index] is null) return;
|
|
866 index++;
|
|
867 }
|
|
868 if (index is length_) return;
|
|
869 System.arraycopy (modalShells, index + 1, modalShells, index, --length_ - index);
|
|
870 modalShells [length_] = null;
|
|
871 if (index is 0 && modalShells [0] is null) modalShells = null;
|
|
872 Shell [] shells = getShells ();
|
|
873 for (int i=0; i<shells.length; i++) shells [i].updateModal ();
|
|
874 }
|
|
875
|
|
876 /**
|
|
877 * Requests that the connection between SWT and the underlying
|
|
878 * operating system be closed.
|
|
879 *
|
|
880 * @exception SWTException <ul>
|
|
881 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
882 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
883 * </ul>
|
|
884 *
|
|
885 * @see Device#dispose
|
|
886 *
|
|
887 * @since 2.0
|
|
888 */
|
|
889 public void close () {
|
|
890 checkDevice ();
|
|
891 Event event = new Event ();
|
|
892 sendEvent (SWT.Close, event);
|
|
893 if (event.doit) dispose ();
|
|
894 }
|
|
895
|
|
896 /**
|
|
897 * Creates the device in the operating system. If the device
|
|
898 * does not have a handle, this method may do nothing depending
|
|
899 * on the device.
|
|
900 * <p>
|
|
901 * This method is called before <code>init</code>.
|
|
902 * </p>
|
|
903 *
|
|
904 * @param data the DeviceData which describes the receiver
|
|
905 *
|
|
906 * @see #init
|
|
907 */
|
|
908 protected override void create (DeviceData data) {
|
|
909 checkSubclass ();
|
|
910 checkDisplay(thread = Thread.getThis (), false);
|
|
911 createDisplay (data);
|
|
912 register (this);
|
|
913 if (Default is null) Default = this;
|
|
914 }
|
|
915
|
|
916 private static extern(C) int XErrorHandler( void*, XErrorEvent* ){
|
|
917 getDwtLogger().error ( __FILE__, __LINE__, "*** XError" );
|
|
918 byte* p;
|
|
919 *p = 3;
|
|
920 return 0;
|
|
921 }
|
|
922
|
|
923 void createDisplay (DeviceData data) {
|
|
924 /* Required for g_main_context_wakeup */
|
|
925 if (!OS.g_thread_supported ()) {
|
|
926 OS.g_thread_init (null);
|
|
927 }
|
|
928 OS.gtk_set_locale();
|
|
929 int cnt = 2;
|
|
930 char*[] args = [ "name".ptr, "--sync".ptr, null ];
|
|
931 char** a = args.ptr;
|
|
932 if (!OS.gtk_init_check (&cnt, &a )) {
|
|
933 }
|
|
934 assert( cnt is 1 );
|
|
935 if (OS.GDK_WINDOWING_X11 ()) xDisplay = cast(void*) OS.GDK_DISPLAY ();
|
|
936
|
|
937 OS.XSetErrorHandler( &Display.XErrorHandler );
|
|
938 char* ptr = OS.gtk_check_version (MAJOR, MINOR, MICRO);
|
|
939 if (ptr !is null) {
|
|
940 char [] buffer = fromStringz(ptr);
|
|
941 getDwtLogger().warn (__FILE__, __LINE__,"***WARNING: {}", buffer );
|
|
942 getDwtLogger().warn (__FILE__, __LINE__,"***WARNING: SWT requires GTK {}.{}.{}", MAJOR, MINOR, MICRO );
|
|
943 int major = OS.gtk_major_version (), minor = OS.gtk_minor_version (), micro = OS.gtk_micro_version ();
|
|
944 getDwtLogger().warn (__FILE__, __LINE__,"***WARNING: Detected: {}.{}.{}", major, minor, micro);
|
|
945 }
|
|
946 if (fixed_type is 0) {
|
|
947 GTypeInfo* fixed_info = new GTypeInfo ();
|
|
948 fixed_info.class_size = GtkFixedClass.sizeof;
|
|
949 fixed_info.class_init = & fixedClassInitProcFunc;
|
|
950 fixed_info.instance_size = GtkFixed.sizeof;
|
|
951 fixed_type = OS.g_type_register_static (OS.GTK_TYPE_FIXED (), "SwtFixed".ptr, fixed_info, 0);
|
|
952 }
|
|
953 if (text_renderer_type is 0) {
|
|
954 GTypeInfo* renderer_info = new GTypeInfo ();
|
|
955 renderer_info.class_size = GtkCellRendererTextClass.sizeof;
|
|
956 renderer_info.class_init = & rendererClassInitProcFunc;
|
|
957 renderer_info.instance_size = GtkCellRendererText.sizeof;
|
|
958 text_renderer_type = OS.g_type_register_static (OS.GTK_TYPE_CELL_RENDERER_TEXT (), "SwtTextRenderer".ptr, renderer_info, 0);
|
|
959 }
|
|
960 if (pixbuf_renderer_type is 0) {
|
|
961 GTypeInfo* renderer_info = new GTypeInfo ();
|
|
962 renderer_info.class_size = GtkCellRendererPixbufClass.sizeof;
|
|
963 renderer_info.class_init = & rendererClassInitProcFunc;
|
|
964 renderer_info.instance_size = GtkCellRendererPixbuf.sizeof;
|
|
965 pixbuf_renderer_type = OS.g_type_register_static (OS.GTK_TYPE_CELL_RENDERER_PIXBUF (), "SwtPixbufRenderer".ptr, renderer_info, 0);
|
|
966 }
|
|
967 if (toggle_renderer_type is 0) {
|
|
968 GTypeInfo* renderer_info = new GTypeInfo ();
|
|
969 renderer_info.class_size = GtkCellRendererToggleClass.sizeof;
|
|
970 renderer_info.class_init = & rendererClassInitProcFunc;
|
|
971 renderer_info.instance_size = GtkCellRendererToggle.sizeof;
|
|
972 toggle_renderer_type = OS.g_type_register_static (OS.GTK_TYPE_CELL_RENDERER_TOGGLE (), "SwtToggleRenderer".ptr, renderer_info, 0);
|
|
973 }
|
|
974
|
|
975 OS.gtk_widget_set_default_direction (OS.GTK_TEXT_DIR_LTR);
|
|
976 OS.gdk_rgb_init ();
|
|
977 char* p = toStringz(APP_NAME);
|
|
978 OS.g_set_prgname (p);
|
|
979 OS.gdk_set_program_class (p);
|
|
980 OS.gtk_rc_parse_string ("style \"swt-flat\" { GtkToolbar::shadow-type = none } widget \"*.swt-toolbar-flat\" style : highest \"swt-flat\"".ptr);
|
|
981
|
|
982 /* Initialize the hidden shell */
|
|
983 shellHandle = OS.gtk_window_new (OS.GTK_WINDOW_TOPLEVEL);
|
|
984 if (shellHandle is null) SWT.error (SWT.ERROR_NO_HANDLES);
|
|
985 OS.gtk_widget_realize (shellHandle);
|
|
986
|
|
987 /* Initialize the filter and event callback */
|
|
988 OS.gdk_event_handler_set (&eventProcFunc, cast(void*)this, null);
|
|
989 //filterProcCallbackData.display = this;
|
|
990 //filterProcCallbackData.data = null;
|
|
991 //OS.gdk_window_add_filter (null, &filterProcFunc, cast(void*)&filterProcCallbackData );
|
|
992 doWindowAddFilter( &filterProcCallbackData, null, null );
|
|
993 }
|
|
994
|
|
995 /*
|
|
996 * Used by Shell
|
|
997 */
|
|
998 package void doWindowAddFilter( CallbackData* cbdata, GdkWindow* window, GtkWidget* widget ){
|
|
999 cbdata.display = this;
|
|
1000 cbdata.data = widget;
|
|
1001 OS.gdk_window_add_filter (window, &filterProcFunc, cbdata );
|
|
1002 }
|
|
1003
|
|
1004 package void doWindowRemoveFilter( CallbackData* cbdata, GdkWindow* window, GtkWidget* widget ){
|
|
1005 cbdata.display = this;
|
|
1006 cbdata.data = widget;
|
|
1007 OS.gdk_window_remove_filter(window, &filterProcFunc, cbdata );
|
|
1008 }
|
|
1009
|
|
1010 Image createImage (String name) {
|
|
1011 auto style = OS.gtk_widget_get_default_style ();
|
|
1012 String buffer = name;
|
|
1013 auto pixbuf = OS.gtk_icon_set_render_icon (
|
|
1014 OS.gtk_icon_factory_lookup_default (buffer.ptr), style,
|
|
1015 OS.GTK_TEXT_DIR_NONE,
|
|
1016 OS.GTK_STATE_NORMAL,
|
|
1017 OS.GTK_ICON_SIZE_DIALOG, null, null );
|
|
1018 if (pixbuf is null) return null;
|
|
1019 int width = OS.gdk_pixbuf_get_width (pixbuf);
|
|
1020 int height = OS.gdk_pixbuf_get_height (pixbuf);
|
|
1021 int stride = OS.gdk_pixbuf_get_rowstride (pixbuf);
|
|
1022 bool hasAlpha = cast(bool)OS.gdk_pixbuf_get_has_alpha (pixbuf);
|
|
1023 char* pixels = OS.gdk_pixbuf_get_pixels (pixbuf);
|
|
1024 byte [] data = new byte [stride * height];
|
|
1025 memmove (data.ptr, pixels, data.length);
|
|
1026 OS.g_object_unref (pixbuf);
|
|
1027 ImageData imageData = null;
|
|
1028 if (hasAlpha) {
|
|
1029 PaletteData palette = new PaletteData (0xFF000000, 0xFF0000, 0xFF00);
|
|
1030 imageData = new ImageData (width, height, 32, palette);
|
|
1031 byte [] alpha = new byte [stride * height];
|
|
1032 for (int y=0; y<height; y++) {
|
|
1033 for (int x=0; x<width; x++) {
|
|
1034 alpha [y*width+x] = data [y*stride+x*4+3];
|
|
1035 data [y*stride+x*4+3] = 0;
|
|
1036 }
|
|
1037 }
|
|
1038 imageData.setAlphas (0, 0, width * height, alpha, 0);
|
|
1039 } else {
|
|
1040 PaletteData palette = new PaletteData (0xFF0000, 0xFF00, 0xFF);
|
|
1041 imageData = new ImageData (width, height, 24, palette);
|
|
1042 }
|
|
1043 imageData.data = data;
|
|
1044 imageData.bytesPerLine = stride;
|
|
1045 return new Image (this, imageData);
|
|
1046 }
|
|
1047
|
|
1048 static GdkPixbuf* createPixbuf(Image image) {
|
|
1049 int w, h;
|
|
1050 OS.gdk_drawable_get_size (image.pixmap, &w, &h);
|
|
1051 auto colormap = OS.gdk_colormap_get_system ();
|
|
1052 GdkPixbuf* pixbuf;
|
|
1053 bool hasMask = image.mask !is null && OS.gdk_drawable_get_depth (image.mask) is 1;
|
|
1054 if (hasMask) {
|
|
1055 pixbuf = OS.gdk_pixbuf_new (OS.GDK_COLORSPACE_RGB, true, 8, w, h );
|
|
1056 if (pixbuf is null) SWT.error (SWT.ERROR_NO_HANDLES);
|
|
1057 OS.gdk_pixbuf_get_from_drawable (pixbuf, image.pixmap, colormap, 0, 0, 0, 0, w, h);
|
|
1058 auto maskPixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, false, 8, w, h);
|
|
1059 if (maskPixbuf is null) SWT.error (SWT.ERROR_NO_HANDLES);
|
|
1060 OS.gdk_pixbuf_get_from_drawable(maskPixbuf, image.mask, null, 0, 0, 0, 0, w, h);
|
|
1061 int stride = OS.gdk_pixbuf_get_rowstride(pixbuf);
|
|
1062 auto pixels = OS.gdk_pixbuf_get_pixels(pixbuf);
|
|
1063 byte[] line = new byte[stride];
|
|
1064 int maskStride = OS.gdk_pixbuf_get_rowstride(maskPixbuf);
|
|
1065 auto maskPixels = OS.gdk_pixbuf_get_pixels(maskPixbuf);
|
|
1066 byte[] maskLine = new byte[maskStride];
|
|
1067 for (int y=0; y<h; y++) {
|
|
1068 auto offset = pixels + (y * stride);
|
|
1069 memmove(line.ptr, offset, stride);
|
|
1070 auto maskOffset = maskPixels + (y * maskStride);
|
|
1071 memmove(maskLine.ptr, maskOffset, maskStride);
|
|
1072 for (int x=0; x<w; x++) {
|
|
1073 if (maskLine[x * 3] is 0) {
|
|
1074 line[x * 4 + 3] = 0;
|
|
1075 }
|
|
1076 }
|
|
1077 memmove(offset, line.ptr, stride);
|
|
1078 }
|
|
1079 OS.g_object_unref(maskPixbuf);
|
|
1080 } else {
|
|
1081 ImageData data = image.getImageData ();
|
|
1082 bool hasAlpha = data.getTransparencyType () is SWT.TRANSPARENCY_ALPHA;
|
|
1083 pixbuf = OS.gdk_pixbuf_new (OS.GDK_COLORSPACE_RGB, hasAlpha, 8, w, h);
|
|
1084 if (pixbuf is null) SWT.error (SWT.ERROR_NO_HANDLES);
|
|
1085 OS.gdk_pixbuf_get_from_drawable (pixbuf, image.pixmap, colormap, 0, 0, 0, 0, w, h);
|
|
1086 if (hasAlpha) {
|
|
1087 byte [] alpha = data.alphaData;
|
|
1088 int stride = OS.gdk_pixbuf_get_rowstride (pixbuf);
|
|
1089 auto pixels = OS.gdk_pixbuf_get_pixels (pixbuf);
|
|
1090 byte [] line = new byte [stride];
|
|
1091 for (int y = 0; y < h; y++) {
|
|
1092 auto offset = pixels + (y * stride);
|
|
1093 memmove (line.ptr, offset, stride);
|
|
1094 for (int x = 0; x < w; x++) {
|
|
1095 line [x*4+3] = alpha [y*w+x];
|
|
1096 }
|
|
1097 memmove (offset, line.ptr, stride);
|
|
1098 }
|
|
1099 }
|
|
1100 }
|
|
1101 return pixbuf;
|
|
1102 }
|
|
1103
|
|
1104 static void deregister (Display display) {
|
|
1105 synchronized (Device.classinfo) {
|
|
1106 for (int i=0; i<Displays.length; i++) {
|
|
1107 if (display is Displays [i]) Displays [i] = null;
|
|
1108 }
|
|
1109 }
|
|
1110 }
|
|
1111
|
|
1112 /**
|
|
1113 * Destroys the device in the operating system and releases
|
|
1114 * the device's handle. If the device does not have a handle,
|
|
1115 * this method may do nothing depending on the device.
|
|
1116 * <p>
|
|
1117 * This method is called after <code>release</code>.
|
|
1118 * </p>
|
|
1119 * @see Device#dispose
|
|
1120 * @see #release
|
|
1121 */
|
|
1122 protected override void destroy () {
|
|
1123 if (this is Default) Default = null;
|
|
1124 deregister (this);
|
|
1125 destroyDisplay ();
|
|
1126 }
|
|
1127
|
|
1128 void destroyDisplay () {
|
|
1129 }
|
|
1130
|
|
1131 static extern(C) int /*long*/ emissionFunc (GSignalInvocationHint* ihint, uint n_param_values, GValue* param_values, void* data) {
|
|
1132 auto cb = cast(CallbackData*)data;
|
|
1133 return cb.display.emissionProc( ihint, n_param_values, param_values, cb.data );
|
|
1134 }
|
|
1135
|
|
1136 int /*long*/ emissionProc (GSignalInvocationHint* ihint, uint n_param_values, GValue* param_values, void* data) {
|
|
1137 if (OS.gtk_widget_get_toplevel (OS.g_value_peek_pointer(param_values)) is data) {
|
|
1138 OS.gtk_widget_set_direction (OS.g_value_peek_pointer(param_values), OS.GTK_TEXT_DIR_RTL);
|
|
1139 }
|
|
1140 return 1;
|
|
1141 }
|
|
1142
|
|
1143 /**
|
|
1144 * Returns the display which the given thread is the
|
|
1145 * user-interface thread for, or null if the given thread
|
|
1146 * is not a user-interface thread for any display. Specifying
|
|
1147 * <code>null</code> as the thread will return <code>null</code>
|
|
1148 * for the display.
|
|
1149 *
|
|
1150 * @param thread the user-interface thread
|
|
1151 * @return the display for the given thread
|
|
1152 */
|
|
1153 public static Display findDisplay (Thread thread) {
|
|
1154 synchronized (Device.classinfo) {
|
|
1155 for (int i=0; i<Displays.length; i++) {
|
|
1156 Display display = Displays [i];
|
|
1157 if (display !is null && display.thread is thread) {
|
|
1158 return display;
|
|
1159 }
|
|
1160 }
|
|
1161 return null;
|
|
1162 }
|
|
1163 }
|
|
1164
|
|
1165 /**
|
|
1166 * Causes the <code>run()</code> method of the runnable to
|
|
1167 * be invoked by the user-interface thread just before the
|
|
1168 * receiver is disposed. Specifying a <code>null</code> runnable
|
|
1169 * is ignored.
|
|
1170 *
|
|
1171 * @param runnable code to run at dispose time.
|
|
1172 *
|
|
1173 * @exception SWTException <ul>
|
|
1174 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1175 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1176 * </ul>
|
|
1177 */
|
|
1178 public void disposeExec (Runnable runnable) {
|
|
1179 checkDevice ();
|
|
1180 if (disposeList is null) disposeList = new Runnable [4];
|
|
1181 for (int i=0; i<disposeList.length; i++) {
|
|
1182 if (disposeList [i] is null) {
|
|
1183 disposeList [i] = runnable;
|
|
1184 return;
|
|
1185 }
|
|
1186 }
|
|
1187 Runnable [] newDisposeList = new Runnable [disposeList.length + 4];
|
|
1188 SimpleType!(Runnable).arraycopy (disposeList, 0, newDisposeList, 0, disposeList.length);
|
|
1189 newDisposeList [disposeList.length] = runnable;
|
|
1190 disposeList = newDisposeList;
|
|
1191 }
|
|
1192
|
|
1193 /**
|
|
1194 * Does whatever display specific cleanup is required, and then
|
|
1195 * uses the code in <code>SWTError.error</code> to handle the error.
|
|
1196 *
|
|
1197 * @param code the descriptive error code
|
|
1198 *
|
|
1199 * @see SWTError#error
|
|
1200 */
|
|
1201 void error (int code) {
|
|
1202 SWT.error (code);
|
|
1203 }
|
|
1204
|
|
1205 private static extern(C) void eventProcFunc (GdkEvent* event, void* data) {
|
|
1206 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
1207 Display disp = cast(Display)data;
|
|
1208 disp.eventProcMeth(event);
|
|
1209 }
|
|
1210 void eventProcMeth (GdkEvent* event) {
|
|
1211 /*
|
|
1212 * Use gdk_event_get_time() rather than event.time or
|
|
1213 * gtk_get_current_event_time(). If the event does not
|
|
1214 * have a time stamp, then the field will contain garbage.
|
|
1215 * Note that calling gtk_get_current_event_time() from
|
|
1216 * outside of gtk_main_do_event() seems to always
|
|
1217 * return zero.
|
|
1218 */
|
|
1219 int time = OS.gdk_event_get_time (event);
|
|
1220 if (time !is 0) lastEventTime = time;
|
|
1221
|
|
1222 int eventType = OS.GDK_EVENT_TYPE (event);
|
|
1223 switch (eventType) {
|
|
1224 case OS.GDK_BUTTON_PRESS:
|
|
1225 case OS.GDK_KEY_PRESS:
|
|
1226 lastUserEventTime = time;
|
|
1227 default:
|
|
1228 }
|
|
1229 bool dispatch = true;
|
|
1230 if (dispatchEvents !is null) {
|
|
1231 dispatch = false;
|
|
1232 for (int i = 0; i < dispatchEvents.length; i++) {
|
|
1233 if (eventType is dispatchEvents [i]) {
|
|
1234 dispatch = true;
|
|
1235 break;
|
|
1236 }
|
|
1237 }
|
|
1238 }
|
|
1239 if (!dispatch) {
|
|
1240 addGdkEvent (OS.gdk_event_copy (event));
|
|
1241 return 0;
|
|
1242 }
|
|
1243 OS.gtk_main_do_event (event);
|
|
1244 if (dispatchEvents is null) putGdkEvents ();
|
|
1245 return 0;
|
|
1246 }
|
|
1247
|
|
1248 /**
|
|
1249 * Given the operating system handle for a widget, returns
|
|
1250 * the instance of the <code>Widget</code> subclass which
|
|
1251 * represents it in the currently running application, if
|
|
1252 * such exists, or null if no matching widget can be found.
|
|
1253 * <p>
|
|
1254 * <b>IMPORTANT:</b> This method should not be called from
|
|
1255 * application code. The arguments are platform-specific.
|
|
1256 * </p>
|
|
1257 *
|
|
1258 * @param handle the handle for the widget
|
|
1259 * @return the SWT widget that the handle represents
|
|
1260 *
|
|
1261 * @exception SWTException <ul>
|
|
1262 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1263 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1264 * </ul>
|
|
1265 */
|
|
1266 public Widget findWidget (GtkWidget* handle) {
|
|
1267 checkDevice ();
|
|
1268 return getWidget (handle);
|
|
1269 }
|
|
1270
|
|
1271 /**
|
|
1272 * Given the operating system handle for a widget,
|
|
1273 * and widget-specific id, returns the instance of
|
|
1274 * the <code>Widget</code> subclass which represents
|
|
1275 * the handle/id pair in the currently running application,
|
|
1276 * if such exists, or null if no matching widget can be found.
|
|
1277 * <p>
|
|
1278 * <b>IMPORTANT:</b> This method should not be called from
|
|
1279 * application code. The arguments are platform-specific.
|
|
1280 * </p>
|
|
1281 *
|
|
1282 * @param handle the handle for the widget
|
|
1283 * @param id the id for the subwidget (usually an item)
|
|
1284 * @return the SWT widget that the handle/id pair represents
|
|
1285 *
|
|
1286 * @exception SWTException <ul>
|
|
1287 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1288 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1289 * </ul>
|
|
1290 *
|
|
1291 * @since 3.1
|
|
1292 */
|
|
1293 public Widget findWidget (GtkWidget* handle, int id) {
|
|
1294 checkDevice ();
|
|
1295 return null;
|
|
1296 }
|
|
1297
|
|
1298 /**
|
|
1299 * Given a widget and a widget-specific id, returns the
|
|
1300 * instance of the <code>Widget</code> subclass which represents
|
|
1301 * the widget/id pair in the currently running application,
|
|
1302 * if such exists, or null if no matching widget can be found.
|
|
1303 *
|
|
1304 * @param widget the widget
|
|
1305 * @param id the id for the subwidget (usually an item)
|
|
1306 * @return the SWT subwidget (usually an item) that the widget/id pair represents
|
|
1307 *
|
|
1308 * @exception SWTException <ul>
|
|
1309 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1310 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1311 * </ul>
|
|
1312 *
|
|
1313 * @since 3.3
|
|
1314 */
|
|
1315 public Widget findWidget (Widget widget, int /*long*/ id) {
|
|
1316 checkDevice ();
|
|
1317 return null;
|
|
1318 }
|
|
1319
|
|
1320 private static extern(C) void fixedClassInitProcFunc (void* g_class, void* class_data) {
|
|
1321 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
1322 GtkWidgetClass* klass = cast(GtkWidgetClass*)g_class;
|
|
1323 klass.map = &fixedMapProcFunc;
|
|
1324 oldFixedSizeAllocateProc = klass.size_allocate;
|
|
1325 klass.size_allocate = &fixedSizeAllocateProc;
|
|
1326 }
|
|
1327
|
|
1328 private static extern(C) void fixedMapProcFunc (GtkWidget * handle) {
|
|
1329 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
1330 Display display = getCurrent ();
|
|
1331 Widget widget = display.getWidget (handle);
|
|
1332 if (widget !is null) widget.fixedMapProc (handle);
|
|
1333 }
|
|
1334
|
|
1335 private static extern(C) static void fixedSizeAllocateProc (GtkWidget* handle, GtkAllocation* allocation) {
|
|
1336 Display display = getCurrent ();
|
|
1337 Widget widget = display.getWidget (handle);
|
|
1338 if (widget !is null) return widget.fixedSizeAllocateProc (handle, allocation);
|
|
1339 return oldFixedSizeAllocateProc(handle, allocation);
|
|
1340 }
|
|
1341
|
|
1342 private static extern(C) void rendererClassInitProcFunc (void* g_class, void* class_data) {
|
|
1343 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
1344 GtkCellRendererClass* klass = cast(GtkCellRendererClass*)g_class;
|
|
1345 klass.render = &rendererRenderProcFunc;
|
|
1346 klass.get_size = &rendererGetSizeProcFunc;
|
|
1347
|
|
1348 }
|
|
1349 private static extern(C) void rendererGetSizeProcFunc(
|
|
1350 GtkCellRenderer *cell,
|
|
1351 GtkWidget *handle,
|
|
1352 GdkRectangle *cell_area,
|
|
1353 int *x_offset,
|
|
1354 int *y_offset,
|
|
1355 int *width,
|
|
1356 int *height)
|
|
1357 {
|
|
1358 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
1359 Display display = getCurrent ();
|
|
1360 Widget widget = display.getWidget (handle);
|
|
1361 if (widget !is null) widget.rendererGetSizeProc (cell, handle, cell_area, x_offset, y_offset, width, height);
|
|
1362 }
|
|
1363 private static extern(C) void rendererRenderProcFunc(GtkCellRenderer * cell, GdkDrawable * window, GtkWidget * handle, GdkRectangle *background_area, GdkRectangle *cell_area, GdkRectangle *expose_area, int flags){
|
|
1364 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
1365 Display display = getCurrent ();
|
|
1366 Widget widget = display.getWidget (handle);
|
|
1367 if (widget !is null) widget.rendererRenderProc (cell, window, handle, background_area, cell_area, expose_area, flags);
|
|
1368 }
|
|
1369
|
|
1370 void flushExposes (GdkWindow* window, bool all) {
|
|
1371 OS.gdk_flush ();
|
|
1372 OS.gdk_flush ();
|
|
1373 if (OS.GDK_WINDOWING_X11 ()) {
|
|
1374 this.flushWindow = window;
|
|
1375 this.flushAll = all;
|
|
1376 auto xDisplay = OS.GDK_DISPLAY ();
|
|
1377 auto xEvent = cast(XEvent*)OS.g_malloc (XEvent.sizeof);
|
|
1378 OS.XCheckIfEvent (xDisplay, xEvent, &checkIfEventProcFunc, cast(char*)this );
|
|
1379 OS.g_free (xEvent);
|
|
1380 this.flushWindow = null;
|
|
1381 }
|
|
1382 }
|
|
1383
|
|
1384 /**
|
|
1385 * Returns the currently active <code>Shell</code>, or null
|
|
1386 * if no shell belonging to the currently running application
|
|
1387 * is active.
|
|
1388 *
|
|
1389 * @return the active shell or null
|
|
1390 *
|
|
1391 * @exception SWTException <ul>
|
|
1392 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1393 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1394 * </ul>
|
|
1395 */
|
|
1396 public Shell getActiveShell () {
|
|
1397 checkDevice ();
|
|
1398 return activeShell;
|
|
1399 }
|
|
1400
|
|
1401 /**
|
|
1402 * Returns a rectangle describing the receiver's size and location. Note that
|
|
1403 * on multi-monitor systems the origin can be negative.
|
|
1404 *
|
|
1405 * @return the bounding rectangle
|
|
1406 *
|
|
1407 * @exception SWTException <ul>
|
|
1408 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1409 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1410 * </ul>
|
|
1411 */
|
|
1412 public override Rectangle getBounds () {
|
|
1413 checkDevice ();
|
|
1414 return new Rectangle (0, 0, OS.gdk_screen_width (), OS.gdk_screen_height ());
|
|
1415 }
|
|
1416
|
|
1417 /**
|
|
1418 * Returns the display which the currently running thread is
|
|
1419 * the user-interface thread for, or null if the currently
|
|
1420 * running thread is not a user-interface thread for any display.
|
|
1421 *
|
|
1422 * @return the current display
|
|
1423 */
|
|
1424 public static Display getCurrent () {
|
|
1425 return findDisplay (Thread.getThis ());
|
|
1426 }
|
|
1427
|
|
1428 int getCaretBlinkTime () {
|
|
1429 // checkDevice ();
|
|
1430 auto settings = OS.gtk_settings_get_default ();
|
|
1431 if (settings is null) return 500;
|
|
1432 int buffer;
|
|
1433 OS.g_object_get1 (settings, OS.gtk_cursor_blink.ptr, &buffer );
|
|
1434 if (buffer is 0) return 0;
|
|
1435 OS.g_object_get1 (settings, OS.gtk_cursor_blink_time.ptr, &buffer);
|
|
1436 if (buffer is 0) return 500;
|
|
1437 /*
|
|
1438 * By experimentation, GTK application don't use the whole
|
|
1439 * blink cycle time. Instead, they divide up the time, using
|
|
1440 * an effective blink rate of about 1/2 the total time.
|
|
1441 */
|
|
1442 return buffer / 2;
|
|
1443 }
|
|
1444
|
|
1445 /**
|
|
1446 * Returns the control which the on-screen pointer is currently
|
|
1447 * over top of, or null if it is not currently over one of the
|
|
1448 * controls built by the currently running application.
|
|
1449 *
|
|
1450 * @return the control under the cursor
|
|
1451 *
|
|
1452 * @exception SWTException <ul>
|
|
1453 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1454 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1455 * </ul>
|
|
1456 */
|
|
1457 public Control getCursorControl () {
|
|
1458 checkDevice();
|
|
1459 int x, y;
|
|
1460 GtkWidget* handle;
|
|
1461 GtkWidget* user_data;
|
|
1462 auto window = OS.gdk_window_at_pointer (&x, &y);
|
|
1463 if (window !is null) {
|
|
1464 OS.gdk_window_get_user_data (window, cast(void**)&user_data);
|
|
1465 handle = user_data;
|
|
1466 } else {
|
|
1467 /*
|
|
1468 * Feature in GTK. gdk_window_at_pointer() will not return a window
|
|
1469 * if the pointer is over a foreign embedded window. The fix is to use
|
|
1470 * XQueryPointer to find the containing GDK window.
|
|
1471 */
|
|
1472 if (!OS.GDK_WINDOWING_X11 ()) return null;
|
|
1473 OS.gdk_error_trap_push ();
|
|
1474 int unusedInt;
|
|
1475 uint unusedUInt;
|
|
1476 uint unusedPtr;
|
|
1477 uint buffer;
|
|
1478 uint xWindow, xParent = OS.XDefaultRootWindow (xDisplay);
|
|
1479 do {
|
|
1480 if (OS.XQueryPointer (xDisplay, xParent, &unusedPtr, &buffer, &unusedInt, &unusedInt, &unusedInt, &unusedInt, &unusedUInt) is 0) {
|
|
1481 handle = null;
|
|
1482 break;
|
|
1483 }
|
|
1484 if ((xWindow = buffer) !is 0) {
|
|
1485 xParent = xWindow;
|
|
1486 auto gdkWindow = OS.gdk_window_lookup (xWindow);
|
|
1487 if (gdkWindow !is null) {
|
|
1488 OS.gdk_window_get_user_data (gdkWindow, cast(void**)&user_data);
|
|
1489 if (user_data !is null) handle = user_data;
|
|
1490 }
|
|
1491 }
|
|
1492 } while (xWindow !is 0);
|
|
1493 OS.gdk_error_trap_pop ();
|
|
1494 }
|
|
1495 if (handle is null) return null;
|
|
1496 do {
|
|
1497 Widget widget = getWidget (handle);
|
|
1498 if (widget !is null && (null !is cast(Control)widget)) {
|
|
1499 Control control = cast(Control) widget;
|
|
1500 if (control.isEnabled ()) return control;
|
|
1501 }
|
|
1502 } while ((handle = OS.gtk_widget_get_parent (handle)) !is null);
|
|
1503 return null;
|
|
1504 }
|
|
1505
|
|
1506 bool filterEvent (Event event) {
|
|
1507 if (filterTable !is null) filterTable.sendEvent (event);
|
|
1508 return false;
|
|
1509 }
|
|
1510
|
|
1511 bool filters (int eventType) {
|
|
1512 if (filterTable is null) return false;
|
|
1513 return filterTable.hooks (eventType);
|
|
1514 }
|
|
1515
|
|
1516 private static extern(C) int filterProcFunc (GdkXEvent* xEvent, GdkEvent* gdkEvent, void* data) {
|
|
1517 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
1518 auto callbackdata = cast(CallbackData*)data;
|
|
1519 auto disp = callbackdata.display;
|
|
1520 if( disp is null ) return 0;
|
|
1521 auto res = disp.filterProcMeth(xEvent,gdkEvent,callbackdata);
|
|
1522 return res;
|
|
1523 }
|
|
1524
|
|
1525 int filterProcMeth (GdkXEvent* xEvent, GdkEvent* gdkEvent, CallbackData* callbackData) {
|
|
1526 if( callbackData.data is null ){
|
|
1527 /*
|
|
1528 * Feature in GTK. When button 4, 5, 6, or 7 is released, GTK
|
|
1529 * does not deliver a corresponding GTK event. Button 6 and 7
|
|
1530 * are mapped to buttons 4 and 5 in SWT. The fix is to change
|
|
1531 * the button number of the event to a negative number so that
|
|
1532 * it gets dispatched by GTK. SWT has been modified to look
|
|
1533 * for negative button numbers.
|
|
1534 */
|
|
1535 XButtonEvent* mouseEvent = cast(XButtonEvent*) xEvent;
|
|
1536 if (mouseEvent.type is OS.ButtonRelease) {
|
|
1537 switch (mouseEvent.button) {
|
|
1538 case 6:
|
|
1539 case 7:
|
|
1540 mouseEvent.button = -mouseEvent.button;
|
|
1541 break;
|
|
1542 default:
|
|
1543 }
|
|
1544 }
|
|
1545 }
|
|
1546 Widget widget = getWidget (cast(GtkWidget*)callbackData.data);
|
|
1547 if (widget is null) return 0;
|
|
1548 return widget.filterProc (cast(XEvent*)xEvent, gdkEvent, callbackData.data);
|
|
1549 }
|
|
1550
|
|
1551 /**
|
|
1552 * Returns the location of the on-screen pointer relative
|
|
1553 * to the top left corner of the screen.
|
|
1554 *
|
|
1555 * @return the cursor location
|
|
1556 *
|
|
1557 * @exception SWTException <ul>
|
|
1558 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1559 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1560 * </ul>
|
|
1561 */
|
|
1562 public Point getCursorLocation () {
|
|
1563 checkDevice ();
|
|
1564 int x, y;
|
|
1565 OS.gdk_window_get_pointer (null, &x, &y, null);
|
|
1566 return new Point (x, y);
|
|
1567 }
|
|
1568
|
|
1569 /**
|
|
1570 * Returns an array containing the recommended cursor sizes.
|
|
1571 *
|
|
1572 * @return the array of cursor sizes
|
|
1573 *
|
|
1574 * @exception SWTException <ul>
|
|
1575 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1576 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1577 * </ul>
|
|
1578 *
|
|
1579 * @since 3.0
|
|
1580 */
|
|
1581 public Point [] getCursorSizes () {
|
|
1582 checkDevice ();
|
|
1583 return [new Point (16, 16), new Point (32, 32)];
|
|
1584 }
|
|
1585
|
|
1586 /**
|
|
1587 * Returns the application defined property of the receiver
|
|
1588 * with the specified name, or null if it has not been set.
|
|
1589 * <p>
|
|
1590 * Applications may have associated arbitrary objects with the
|
|
1591 * receiver in this fashion. If the objects stored in the
|
|
1592 * properties need to be notified when the display is disposed
|
|
1593 * of, it is the application's responsibility to provide a
|
|
1594 * <code>disposeExec()</code> handler which does so.
|
|
1595 * </p>
|
|
1596 *
|
|
1597 * @param key the name of the property
|
|
1598 * @return the value of the property or null if it has not been set
|
|
1599 *
|
|
1600 * @exception SWTException <ul>
|
|
1601 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1602 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1603 * </ul>
|
|
1604 *
|
|
1605 * @see #setData(String, Object)
|
|
1606 * @see #disposeExec(Runnable)
|
|
1607 */
|
|
1608 public Object getData (String key) {
|
|
1609 checkDevice ();
|
|
1610 // SWT extension: allow null for zero length string
|
|
1611 //if (key is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
1612 if (key.equals (DISPATCH_EVENT_KEY)) {
|
|
1613 return new ArrayWrapperInt(dispatchEvents);
|
|
1614 }
|
|
1615 if (key.equals (GET_MODAL_DIALOG)) {
|
|
1616 return modalDialog;
|
|
1617 }
|
|
1618 if (key.equals (GET_DIRECTION_PROC_KEY)) {
|
|
1619 return new LONG (cast(int) &setDirectionProcFunc);
|
|
1620 }
|
|
1621 if (key.equals (GET_EMISSION_PROC_KEY)) {
|
|
1622 return new LONG (cast(int) &emissionFunc);
|
|
1623 }
|
|
1624 if (keys is null) return null;
|
|
1625 for (int i=0; i<keys.length; i++) {
|
|
1626 if (keys [i].equals(key)) return values [i];
|
|
1627 }
|
|
1628 return null;
|
|
1629 }
|
|
1630
|
|
1631 /**
|
|
1632 * Returns the application defined, display specific data
|
|
1633 * associated with the receiver, or null if it has not been
|
|
1634 * set. The <em>display specific data</em> is a single,
|
|
1635 * unnamed field that is stored with every display.
|
|
1636 * <p>
|
|
1637 * Applications may put arbitrary objects in this field. If
|
|
1638 * the object stored in the display specific data needs to
|
|
1639 * be notified when the display is disposed of, it is the
|
|
1640 * application's responsibility to provide a
|
|
1641 * <code>disposeExec()</code> handler which does so.
|
|
1642 * </p>
|
|
1643 *
|
|
1644 * @return the display specific data
|
|
1645 *
|
|
1646 * @exception SWTException <ul>
|
|
1647 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1648 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1649 * </ul>
|
|
1650 *
|
|
1651 * @see #setData(Object)
|
|
1652 * @see #disposeExec(Runnable)
|
|
1653 */
|
|
1654 public Object getData () {
|
|
1655 checkDevice ();
|
|
1656 return data;
|
|
1657 }
|
|
1658
|
|
1659 /**
|
|
1660 * Returns a point whose x coordinate is the horizontal
|
|
1661 * dots per inch of the display, and whose y coordinate
|
|
1662 * is the vertical dots per inch of the display.
|
|
1663 *
|
|
1664 * @return the horizontal and vertical DPI
|
|
1665 *
|
|
1666 * @exception SWTException <ul>
|
|
1667 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1668 * </ul>
|
|
1669 */
|
|
1670 public override Point getDPI () {
|
|
1671 checkDevice ();
|
|
1672 int widthMM = OS.gdk_screen_width_mm ();
|
|
1673 int width = OS.gdk_screen_width ();
|
|
1674 int dpi = Compatibility.round (254 * width, widthMM * 10);
|
|
1675 return new Point (dpi, dpi);
|
|
1676 }
|
|
1677
|
|
1678 int /*long*/ gtk_fixed_get_type () {
|
|
1679 return fixed_type;
|
|
1680 }
|
|
1681
|
|
1682 int /*long*/ gtk_cell_renderer_text_get_type () {
|
|
1683 return text_renderer_type;
|
|
1684 }
|
|
1685
|
|
1686 int /*long*/ gtk_cell_renderer_pixbuf_get_type () {
|
|
1687 return pixbuf_renderer_type;
|
|
1688 }
|
|
1689
|
|
1690 int /*long*/ gtk_cell_renderer_toggle_get_type () {
|
|
1691 return toggle_renderer_type;
|
|
1692 }
|
|
1693
|
|
1694 /**
|
|
1695 * Returns the default display. One is created (making the
|
|
1696 * thread that invokes this method its user-interface thread)
|
|
1697 * if it did not already exist.
|
|
1698 *
|
|
1699 * @return the default display
|
|
1700 */
|
|
1701 public static Display getDefault () {
|
|
1702 synchronized (Device.classinfo) {
|
|
1703 if (Default is null) Default = new Display ();
|
|
1704 return Default;
|
|
1705 }
|
|
1706 }
|
|
1707
|
|
1708 // /+static bool isValidClass (Class clazz) {
|
|
1709 // //PORTING_TODO String name = clazz.getName ();
|
|
1710 // //PORTING_TODO int index = name.lastIndexOf ('.');
|
|
1711 // //PORTING_TODO return name.substring (0, index + 1)==/*eq*/ PACKAGE_PREFIX;
|
|
1712 // return true;
|
|
1713 // }+/
|
|
1714
|
|
1715 /**
|
|
1716 * Returns the button dismissal alignment, one of <code>LEFT</code> or <code>RIGHT</code>.
|
|
1717 * The button dismissal alignment is the ordering that should be used when positioning the
|
|
1718 * default dismissal button for a dialog. For example, in a dialog that contains an OK and
|
|
1719 * CANCEL button, on platforms where the button dismissal alignment is <code>LEFT</code>, the
|
|
1720 * button ordering should be OK/CANCEL. When button dismissal alignment is <code>RIGHT</code>,
|
|
1721 * the button ordering should be CANCEL/OK.
|
|
1722 *
|
|
1723 * @return the button dismissal order
|
|
1724 *
|
|
1725 * @exception SWTException <ul>
|
|
1726 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1727 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1728 * </ul>
|
|
1729 *
|
|
1730 * @since 2.1
|
|
1731 */
|
|
1732 public int getDismissalAlignment () {
|
|
1733 checkDevice ();
|
|
1734 return SWT.RIGHT;
|
|
1735 }
|
|
1736
|
|
1737 /**
|
|
1738 * Returns the longest duration, in milliseconds, between
|
|
1739 * two mouse button clicks that will be considered a
|
|
1740 * <em>double click</em> by the underlying operating system.
|
|
1741 *
|
|
1742 * @return the double click time
|
|
1743 *
|
|
1744 * @exception SWTException <ul>
|
|
1745 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1746 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1747 * </ul>
|
|
1748 */
|
|
1749 public int getDoubleClickTime () {
|
|
1750 checkDevice ();
|
|
1751 auto settings = OS.gtk_settings_get_default ();
|
|
1752 int buffer;
|
|
1753 OS.g_object_get1 (settings, OS.gtk_double_click_time.ptr, &buffer);
|
|
1754 return buffer;
|
|
1755 }
|
|
1756
|
|
1757 /**
|
|
1758 * Returns the control which currently has keyboard focus,
|
|
1759 * or null if keyboard events are not currently going to
|
|
1760 * any of the controls built by the currently running
|
|
1761 * application.
|
|
1762 *
|
|
1763 * @return the control under the cursor
|
|
1764 *
|
|
1765 * @exception SWTException <ul>
|
|
1766 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1767 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1768 * </ul>
|
|
1769 */
|
|
1770 public Control getFocusControl () {
|
|
1771 checkDevice ();
|
|
1772 if (focusControl !is null && !focusControl.isDisposed ()) {
|
|
1773 return focusControl;
|
|
1774 }
|
|
1775 if (activeShell is null) return null;
|
|
1776 auto shellHandle = activeShell.shellHandle;
|
|
1777 auto handle = OS.gtk_window_get_focus (cast(GtkWindow*)shellHandle);
|
|
1778 if (handle is null) return null;
|
|
1779 do {
|
|
1780 Widget widget = getWidget (handle);
|
|
1781 if (widget !is null && (null !is cast(Control)widget)) {
|
|
1782 Control control = cast(Control) widget;
|
|
1783 return control.isEnabled () ? control : null;
|
|
1784 }
|
|
1785 } while ((handle = OS.gtk_widget_get_parent (handle)) !is null);
|
|
1786 return null;
|
|
1787 }
|
|
1788
|
|
1789 /**
|
|
1790 * Returns true when the high contrast mode is enabled.
|
|
1791 * Otherwise, false is returned.
|
|
1792 * <p>
|
|
1793 * Note: This operation is a hint and is not supported on
|
|
1794 * platforms that do not have this concept.
|
|
1795 * </p>
|
|
1796 *
|
|
1797 * @return the high contrast mode
|
|
1798 *
|
|
1799 * @exception SWTException <ul>
|
|
1800 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1801 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1802 * </ul>
|
|
1803 *
|
|
1804 * @since 3.0
|
|
1805 */
|
|
1806 public bool getHighContrast () {
|
|
1807 checkDevice ();
|
|
1808 return false;
|
|
1809 }
|
|
1810
|
|
1811 public override int getDepth () {
|
|
1812 checkDevice ();
|
|
1813 auto visual = OS.gdk_visual_get_system();
|
|
1814 return visual.depth;
|
|
1815 }
|
|
1816
|
|
1817 /**
|
|
1818 * Returns the maximum allowed depth of icons on this display, in bits per pixel.
|
|
1819 * On some platforms, this may be different than the actual depth of the display.
|
|
1820 *
|
|
1821 * @return the maximum icon depth
|
|
1822 *
|
|
1823 * @exception SWTException <ul>
|
|
1824 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1825 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1826 * </ul>
|
|
1827 *
|
|
1828 * @see Device#getDepth
|
|
1829 */
|
|
1830 public int getIconDepth () {
|
|
1831 checkDevice ();
|
|
1832 return getDepth ();
|
|
1833 }
|
|
1834
|
|
1835 /**
|
|
1836 * Returns an array containing the recommended icon sizes.
|
|
1837 *
|
|
1838 * @return the array of icon sizes
|
|
1839 *
|
|
1840 * @exception SWTException <ul>
|
|
1841 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1842 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1843 * </ul>
|
|
1844 *
|
|
1845 * @see Decorations#setImages(Image[])
|
|
1846 *
|
|
1847 * @since 3.0
|
|
1848 */
|
|
1849 public Point [] getIconSizes () {
|
|
1850 checkDevice ();
|
|
1851 return [new Point (16, 16), new Point (32, 32)];
|
|
1852 }
|
|
1853
|
|
1854 int getLastEventTime () {
|
|
1855 return lastEventTime;
|
|
1856 }
|
|
1857
|
|
1858 int getMessageCount () {
|
|
1859 return synchronizer.getMessageCount ();
|
|
1860 }
|
|
1861
|
|
1862 Dialog getModalDialog () {
|
|
1863 return modalDialog;
|
|
1864 }
|
|
1865
|
|
1866 /**
|
|
1867 * Returns the work area, an EWMH property to store the size
|
|
1868 * and position of the screen not covered by dock and panel
|
|
1869 * windows. See http://freedesktop.org/Standards/wm-spec.
|
|
1870 */
|
|
1871 Rectangle getWorkArea() {
|
|
1872 auto atom = OS.gdk_atom_intern ("_NET_WORKAREA".ptr, true);
|
|
1873 if (atom is null/*OS.GDK_NONE*/) return null;
|
|
1874 void* actualType;
|
|
1875 int actualFormat;
|
|
1876 int actualLength;
|
|
1877 char* data;
|
|
1878 if (!OS.gdk_property_get (cast(GdkDrawable*)OS.GDK_ROOT_PARENT (), atom, null/*OS.GDK_NONE*/, 0, 16, 0, &actualType, &actualFormat, &actualLength, &data)) {
|
|
1879 return null;
|
|
1880 }
|
|
1881 Rectangle result = null;
|
|
1882 if (data !is null) {
|
|
1883 if (actualLength is 16) {
|
|
1884 int[] values = (cast(int*)data)[0..4];
|
|
1885 result = new Rectangle (values [0],values [1],values [2],values [3]);
|
|
1886 } else if (actualLength is 32) {
|
|
1887 long[] values = (cast(long*)data)[0..4];
|
|
1888 result = new Rectangle (cast(int)values [0],cast(int)values [1],cast(int)values [2],cast(int)values [3]);
|
|
1889 }
|
|
1890 OS.g_free (data);
|
|
1891 }
|
|
1892 return result;
|
|
1893 }
|
|
1894
|
|
1895 /**
|
|
1896 * Returns an array of monitors attached to the device.
|
|
1897 *
|
|
1898 * @return the array of monitors
|
|
1899 *
|
|
1900 * @since 3.0
|
|
1901 */
|
|
1902 public org.eclipse.swt.widgets.Monitor.Monitor [] getMonitors () {
|
|
1903 checkDevice ();
|
|
1904 org.eclipse.swt.widgets.Monitor.Monitor [] monitors = null;
|
|
1905 Rectangle workArea = getWorkArea();
|
|
1906 auto screen = OS.gdk_screen_get_default ();
|
|
1907 if (screen !is null) {
|
|
1908 int monitorCount = OS.gdk_screen_get_n_monitors (screen);
|
|
1909 if (monitorCount > 0) {
|
|
1910 monitors = new org.eclipse.swt.widgets.Monitor.Monitor [monitorCount];
|
|
1911 GdkRectangle* dest = new GdkRectangle ();
|
|
1912 for (int i = 0; i < monitorCount; i++) {
|
|
1913 OS.gdk_screen_get_monitor_geometry (screen, i, dest);
|
|
1914 auto monitor = new org.eclipse.swt.widgets.Monitor.Monitor ();
|
|
1915 monitor.handle = i;
|
|
1916 monitor.x = dest.x;
|
|
1917 monitor.y = dest.y;
|
|
1918 monitor.width = dest.width;
|
|
1919 monitor.height = dest.height;
|
|
1920 if (i is 0 && workArea !is null) {
|
|
1921 monitor.clientX = workArea.x;
|
|
1922 monitor.clientY = workArea.y;
|
|
1923 monitor.clientWidth = workArea.width;
|
|
1924 monitor.clientHeight = workArea.height;
|
|
1925 } else {
|
|
1926 monitor.clientX = monitor.x;
|
|
1927 monitor.clientY = monitor.y;
|
|
1928 monitor.clientWidth = monitor.width;
|
|
1929 monitor.clientHeight = monitor.height;
|
|
1930 }
|
|
1931 monitors [i] = monitor;
|
|
1932 }
|
|
1933 }
|
|
1934 }
|
|
1935 if (monitors is null) {
|
|
1936 /* No multimonitor support detected, default to one monitor */
|
|
1937 auto monitor = new org.eclipse.swt.widgets.Monitor.Monitor ();
|
|
1938 Rectangle bounds = getBounds ();
|
|
1939 monitor.x = bounds.x;
|
|
1940 monitor.y = bounds.y;
|
|
1941 monitor.width = bounds.width;
|
|
1942 monitor.height = bounds.height;
|
|
1943 if (workArea !is null) {
|
|
1944 monitor.clientX = workArea.x;
|
|
1945 monitor.clientY = workArea.y;
|
|
1946 monitor.clientWidth = workArea.width;
|
|
1947 monitor.clientHeight = workArea.height;
|
|
1948 } else {
|
|
1949 monitor.clientX = monitor.x;
|
|
1950 monitor.clientY = monitor.y;
|
|
1951 monitor.clientWidth = monitor.width;
|
|
1952 monitor.clientHeight = monitor.height;
|
|
1953 }
|
|
1954 monitors = [ monitor ];
|
|
1955 }
|
|
1956 return monitors;
|
|
1957 }
|
|
1958
|
|
1959 /**
|
|
1960 * Returns the primary monitor for that device.
|
|
1961 *
|
|
1962 * @return the primary monitor
|
|
1963 *
|
|
1964 * @since 3.0
|
|
1965 */
|
|
1966 public org.eclipse.swt.widgets.Monitor.Monitor getPrimaryMonitor () {
|
|
1967 checkDevice ();
|
|
1968 auto monitors = getMonitors ();
|
|
1969 return monitors [0];
|
|
1970 }
|
|
1971
|
|
1972 /**
|
|
1973 * Returns a (possibly empty) array containing all shells which have
|
|
1974 * not been disposed and have the receiver as their display.
|
|
1975 *
|
|
1976 * @return the receiver's shells
|
|
1977 *
|
|
1978 * @exception SWTException <ul>
|
|
1979 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
1980 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
1981 * </ul>
|
|
1982 */
|
|
1983 public Shell [] getShells () {
|
|
1984 checkDevice ();
|
|
1985 int index = 0;
|
|
1986 Shell [] result = new Shell [16];
|
|
1987 for (int i = 0; i < widgetTable.length; i++) {
|
|
1988 Widget widget = widgetTable [i];
|
|
1989 if (widget !is null && (null !is cast(Shell)widget)) {
|
|
1990 int j = 0;
|
|
1991 while (j < index) {
|
|
1992 if (result [j] is widget) break;
|
|
1993 j++;
|
|
1994 }
|
|
1995 if (j is index) {
|
|
1996 if (index is result.length) {
|
|
1997 Shell [] newResult = new Shell [index + 16];
|
|
1998 System.arraycopy (result, 0, newResult, 0, index);
|
|
1999 result = newResult;
|
|
2000 }
|
|
2001 result [index++] = cast(Shell) widget;
|
|
2002 }
|
|
2003 }
|
|
2004 }
|
|
2005 if (index is result.length) return result;
|
|
2006 Shell [] newResult = new Shell [index];
|
|
2007 System.arraycopy (result, 0, newResult, 0, index);
|
|
2008 return newResult;
|
|
2009 }
|
|
2010
|
|
2011 /**
|
|
2012 * Gets the synchronizer used by the display.
|
|
2013 *
|
|
2014 * @return the receiver's synchronizer
|
|
2015 *
|
|
2016 * @exception SWTException <ul>
|
|
2017 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
2018 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
2019 * </ul>
|
|
2020 *
|
|
2021 * @since 3.4
|
|
2022 */
|
|
2023 public Synchronizer getSynchronizer () {
|
|
2024 checkDevice ();
|
|
2025 return synchronizer;
|
|
2026 }
|
|
2027
|
|
2028 /**
|
|
2029 * Returns the thread that has invoked <code>syncExec</code>
|
|
2030 * or null if no such runnable is currently being invoked by
|
|
2031 * the user-interface thread.
|
|
2032 * <p>
|
|
2033 * Note: If a runnable invoked by asyncExec is currently
|
|
2034 * running, this method will return null.
|
|
2035 * </p>
|
|
2036 *
|
|
2037 * @return the receiver's sync-interface thread
|
|
2038 *
|
|
2039 * @exception SWTException <ul>
|
|
2040 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
2041 * </ul>
|
|
2042 */
|
|
2043 public Thread getSyncThread () {
|
|
2044 synchronized (Device.classinfo) {
|
|
2045 if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
|
|
2046 return synchronizer.syncThread;
|
|
2047 }
|
|
2048 }
|
|
2049
|
|
2050 /**
|
|
2051 * Returns the matching standard color for the given
|
|
2052 * constant, which should be one of the color constants
|
|
2053 * specified in class <code>SWT</code>. Any value other
|
|
2054 * than one of the SWT color constants which is passed
|
|
2055 * in will result in the color black. This color should
|
|
2056 * not be free'd because it was allocated by the system,
|
|
2057 * not the application.
|
|
2058 *
|
|
2059 * @param id the color constant
|
|
2060 * @return the matching color
|
|
2061 *
|
|
2062 * @exception SWTException <ul>
|
|
2063 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
2064 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
2065 * </ul>
|
|
2066 *
|
|
2067 * @see SWT
|
|
2068 */
|
|
2069 public override Color getSystemColor (int id) {
|
|
2070 checkDevice ();
|
|
2071 GdkColor* gdkColor = null;
|
|
2072 switch (id) {
|
|
2073 case SWT.COLOR_INFO_FOREGROUND: gdkColor = COLOR_INFO_FOREGROUND; break;
|
|
2074 case SWT.COLOR_INFO_BACKGROUND: gdkColor = COLOR_INFO_BACKGROUND; break;
|
|
2075 case SWT.COLOR_TITLE_FOREGROUND: gdkColor = COLOR_TITLE_FOREGROUND; break;
|
|
2076 case SWT.COLOR_TITLE_BACKGROUND: gdkColor = COLOR_TITLE_BACKGROUND; break;
|
|
2077 case SWT.COLOR_TITLE_BACKGROUND_GRADIENT: gdkColor = COLOR_TITLE_BACKGROUND_GRADIENT; break;
|
|
2078 case SWT.COLOR_TITLE_INACTIVE_FOREGROUND: gdkColor = COLOR_TITLE_INACTIVE_FOREGROUND; break;
|
|
2079 case SWT.COLOR_TITLE_INACTIVE_BACKGROUND: gdkColor = COLOR_TITLE_INACTIVE_BACKGROUND; break;
|
|
2080 case SWT.COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT: gdkColor = COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT; break;
|
|
2081 case SWT.COLOR_WIDGET_DARK_SHADOW: gdkColor = COLOR_WIDGET_DARK_SHADOW; break;
|
|
2082 case SWT.COLOR_WIDGET_NORMAL_SHADOW: gdkColor = COLOR_WIDGET_NORMAL_SHADOW; break;
|
|
2083 case SWT.COLOR_WIDGET_LIGHT_SHADOW: gdkColor = COLOR_WIDGET_LIGHT_SHADOW; break;
|
|
2084 case SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW: gdkColor = COLOR_WIDGET_HIGHLIGHT_SHADOW; break;
|
|
2085 case SWT.COLOR_WIDGET_BACKGROUND: gdkColor = COLOR_WIDGET_BACKGROUND; break;
|
|
2086 case SWT.COLOR_WIDGET_FOREGROUND: gdkColor = COLOR_WIDGET_FOREGROUND; break;
|
|
2087 case SWT.COLOR_WIDGET_BORDER: gdkColor = COLOR_WIDGET_BORDER; break;
|
|
2088 case SWT.COLOR_LIST_FOREGROUND: gdkColor = COLOR_LIST_FOREGROUND; break;
|
|
2089 case SWT.COLOR_LIST_BACKGROUND: gdkColor = COLOR_LIST_BACKGROUND; break;
|
|
2090 case SWT.COLOR_LIST_SELECTION: gdkColor = COLOR_LIST_SELECTION; break;
|
|
2091 case SWT.COLOR_LIST_SELECTION_TEXT: gdkColor = COLOR_LIST_SELECTION_TEXT; break;
|
|
2092 default:
|
|
2093 return super.getSystemColor (id);
|
|
2094 }
|
|
2095 if (gdkColor is null) return super.getSystemColor (SWT.COLOR_BLACK);
|
|
2096 return Color.gtk_new (this, gdkColor);
|
|
2097 }
|
|
2098
|
|
2099 /**
|
|
2100 * Returns the matching standard platform cursor for the given
|
|
2101 * constant, which should be one of the cursor constants
|
|
2102 * specified in class <code>SWT</code>. This cursor should
|
|
2103 * not be free'd because it was allocated by the system,
|
|
2104 * not the application. A value of <code>null</code> will
|
|
2105 * be returned if the supplied constant is not an SWT cursor
|
|
2106 * constant.
|
|
2107 *
|
|
2108 * @param id the SWT cursor constant
|
|
2109 * @return the corresponding cursor or <code>null</code>
|
|
2110 *
|
|
2111 * @exception SWTException <ul>
|
|
2112 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
2113 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
2114 * </ul>
|
|
2115 *
|
|
2116 * @see SWT#CURSOR_ARROW
|
|
2117 * @see SWT#CURSOR_WAIT
|
|
2118 * @see SWT#CURSOR_CROSS
|
|
2119 * @see SWT#CURSOR_APPSTARTING
|
|
2120 * @see SWT#CURSOR_HELP
|
|
2121 * @see SWT#CURSOR_SIZEALL
|
|
2122 * @see SWT#CURSOR_SIZENESW
|
|
2123 * @see SWT#CURSOR_SIZENS
|
|
2124 * @see SWT#CURSOR_SIZENWSE
|
|
2125 * @see SWT#CURSOR_SIZEWE
|
|
2126 * @see SWT#CURSOR_SIZEN
|
|
2127 * @see SWT#CURSOR_SIZES
|
|
2128 * @see SWT#CURSOR_SIZEE
|
|
2129 * @see SWT#CURSOR_SIZEW
|
|
2130 * @see SWT#CURSOR_SIZENE
|
|
2131 * @see SWT#CURSOR_SIZESE
|
|
2132 * @see SWT#CURSOR_SIZESW
|
|
2133 * @see SWT#CURSOR_SIZENW
|
|
2134 * @see SWT#CURSOR_UPARROW
|
|
2135 * @see SWT#CURSOR_IBEAM
|
|
2136 * @see SWT#CURSOR_NO
|
|
2137 * @see SWT#CURSOR_HAND
|
|
2138 *
|
|
2139 * @since 3.0
|
|
2140 */
|
|
2141 public Cursor getSystemCursor (int id) {
|
|
2142 checkDevice ();
|
|
2143 if (!(0 <= id && id < cursors.length)) return null;
|
|
2144 if (cursors [id] is null) {
|
|
2145 cursors [id] = new Cursor (this, id);
|
|
2146 }
|
|
2147 return cursors [id];
|
|
2148 }
|
|
2149
|
|
2150 /**
|
|
2151 * Returns the matching standard platform image for the given
|
|
2152 * constant, which should be one of the icon constants
|
|
2153 * specified in class <code>SWT</code>. This image should
|
|
2154 * not be free'd because it was allocated by the system,
|
|
2155 * not the application. A value of <code>null</code> will
|
|
2156 * be returned either if the supplied constant is not an
|
|
2157 * SWT icon constant or if the platform does not define an
|
|
2158 * image that corresponds to the constant.
|
|
2159 *
|
|
2160 * @param id the SWT icon constant
|
|
2161 * @return the corresponding image or <code>null</code>
|
|
2162 *
|
|
2163 * @exception SWTException <ul>
|
|
2164 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
2165 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
2166 * </ul>
|
|
2167 *
|
|
2168 * @see SWT#ICON_ERROR
|
|
2169 * @see SWT#ICON_INFORMATION
|
|
2170 * @see SWT#ICON_QUESTION
|
|
2171 * @see SWT#ICON_WARNING
|
|
2172 * @see SWT#ICON_WORKING
|
|
2173 *
|
|
2174 * @since 3.0
|
|
2175 */
|
|
2176 public Image getSystemImage (int id) {
|
|
2177 checkDevice ();
|
|
2178 switch (id) {
|
|
2179 case SWT.ICON_ERROR:
|
|
2180 if (errorImage is null) {
|
|
2181 errorImage = createImage ("gtk-dialog-error"); //$NON-NLS-1$
|
|
2182 }
|
|
2183 return errorImage;
|
|
2184 case SWT.ICON_INFORMATION:
|
|
2185 case SWT.ICON_WORKING:
|
|
2186 if (infoImage is null) {
|
|
2187 infoImage = createImage ("gtk-dialog-info"); //$NON-NLS-1$
|
|
2188 }
|
|
2189 return infoImage;
|
|
2190 case SWT.ICON_QUESTION:
|
|
2191 if (questionImage is null) {
|
|
2192 questionImage = createImage ("gtk-dialog-question"); //$NON-NLS-1$
|
|
2193 }
|
|
2194 return questionImage;
|
|
2195 case SWT.ICON_WARNING:
|
|
2196 if (warningImage is null) {
|
|
2197 warningImage = createImage ("gtk-dialog-warning"); //$NON-NLS-1$
|
|
2198 }
|
|
2199 return warningImage;
|
|
2200 default:
|
|
2201 }
|
|
2202 return null;
|
|
2203 }
|
|
2204
|
|
2205 void initializeSystemColors () {
|
|
2206 GdkColor* gdkColor;
|
|
2207
|
|
2208 /* Get Tooltip resources */
|
|
2209 auto tooltipShellHandle = OS.gtk_window_new (OS.GTK_WINDOW_POPUP);
|
|
2210 if (tooltipShellHandle is null) SWT.error (SWT.ERROR_NO_HANDLES);
|
|
2211 // byte[] gtk_tooltips = Converter.wcsToMbcs (null, "gtk-tooltips", true);
|
|
2212 OS.gtk_widget_set_name (tooltipShellHandle, "gtk-tooltips".ptr );
|
|
2213 OS.gtk_widget_realize (tooltipShellHandle);
|
|
2214 auto tooltipStyle = OS.gtk_widget_get_style (tooltipShellHandle);
|
|
2215 gdkColor = new GdkColor();
|
|
2216 OS.gtk_style_get_fg (tooltipStyle, OS.GTK_STATE_NORMAL, gdkColor);
|
|
2217 COLOR_INFO_FOREGROUND = gdkColor;
|
|
2218 gdkColor = new GdkColor();
|
|
2219 OS.gtk_style_get_bg (tooltipStyle, OS.GTK_STATE_NORMAL, gdkColor);
|
|
2220 COLOR_INFO_BACKGROUND = gdkColor;
|
|
2221 OS.gtk_widget_destroy (tooltipShellHandle);
|
|
2222
|
|
2223 /* Get Shell resources */
|
|
2224 auto style = OS.gtk_widget_get_style (shellHandle);
|
|
2225 gdkColor = new GdkColor();
|
|
2226 OS.gtk_style_get_black (style, gdkColor);
|
|
2227 COLOR_WIDGET_DARK_SHADOW = gdkColor;
|
|
2228 gdkColor = new GdkColor();
|
|
2229 OS.gtk_style_get_dark (style, OS.GTK_STATE_NORMAL, gdkColor);
|
|
2230 COLOR_WIDGET_NORMAL_SHADOW = gdkColor;
|
|
2231 gdkColor = new GdkColor();
|
|
2232 OS.gtk_style_get_bg (style, OS.GTK_STATE_NORMAL, gdkColor);
|
|
2233 COLOR_WIDGET_LIGHT_SHADOW = gdkColor;
|
|
2234 gdkColor = new GdkColor();
|
|
2235 OS.gtk_style_get_light (style, OS.GTK_STATE_NORMAL, gdkColor);
|
|
2236 COLOR_WIDGET_HIGHLIGHT_SHADOW = gdkColor;
|
|
2237 gdkColor = new GdkColor();
|
|
2238 OS.gtk_style_get_fg (style, OS.GTK_STATE_NORMAL, gdkColor);
|
|
2239 COLOR_WIDGET_FOREGROUND = gdkColor;
|
|
2240 gdkColor = new GdkColor();
|
|
2241 OS.gtk_style_get_bg (style, OS.GTK_STATE_NORMAL, gdkColor);
|
|
2242 COLOR_WIDGET_BACKGROUND = gdkColor;
|
|
2243 //gdkColor = new GdkColor();
|
|
2244 //OS.gtk_style_get_text (style, OS.GTK_STATE_NORMAL, gdkColor);
|
|
2245 //COLOR_TEXT_FOREGROUND = gdkColor;
|
|
2246 //gdkColor = new GdkColor();
|
|
2247 //OS.gtk_style_get_base (style, OS.GTK_STATE_NORMAL, gdkColor);
|
|
2248 //COLOR_TEXT_BACKGROUND = gdkColor;
|
|
2249 gdkColor = new GdkColor();
|
|
2250 OS.gtk_style_get_text (style, OS.GTK_STATE_NORMAL, gdkColor);
|
|
2251 COLOR_LIST_FOREGROUND = gdkColor;
|
|
2252 gdkColor = new GdkColor();
|
|
2253 OS.gtk_style_get_base (style, OS.GTK_STATE_NORMAL, gdkColor);
|
|
2254 COLOR_LIST_BACKGROUND = gdkColor;
|
|
2255 gdkColor = new GdkColor();
|
|
2256 OS.gtk_style_get_text (style, OS.GTK_STATE_SELECTED, gdkColor);
|
|
2257 COLOR_LIST_SELECTION_TEXT = gdkColor;
|
|
2258 gdkColor = new GdkColor();
|
|
2259 OS.gtk_style_get_base (style, OS.GTK_STATE_SELECTED, gdkColor);
|
|
2260 COLOR_LIST_SELECTION = gdkColor;
|
|
2261 gdkColor = new GdkColor();
|
|
2262 OS.gtk_style_get_bg (style, OS.GTK_STATE_SELECTED, gdkColor);
|
|
2263 COLOR_TITLE_BACKGROUND = gdkColor;
|
|
2264 gdkColor = new GdkColor();
|
|
2265 OS.gtk_style_get_fg (style, OS.GTK_STATE_SELECTED, gdkColor);
|
|
2266 COLOR_TITLE_FOREGROUND = gdkColor;
|
|
2267 gdkColor = new GdkColor();
|
|
2268 OS.gtk_style_get_light (style, OS.GTK_STATE_SELECTED, gdkColor);
|
|
2269 COLOR_TITLE_BACKGROUND_GRADIENT = gdkColor;
|
|
2270 gdkColor = new GdkColor();
|
|
2271 OS.gtk_style_get_bg (style, OS.GTK_STATE_INSENSITIVE, gdkColor);
|
|
2272 COLOR_TITLE_INACTIVE_BACKGROUND = gdkColor;
|
|
2273 gdkColor = new GdkColor();
|
|
2274 OS.gtk_style_get_fg (style, OS.GTK_STATE_INSENSITIVE, gdkColor);
|
|
2275 COLOR_TITLE_INACTIVE_FOREGROUND = gdkColor;
|
|
2276 gdkColor = new GdkColor();
|
|
2277 OS.gtk_style_get_light (style, OS.GTK_STATE_INSENSITIVE, gdkColor);
|
|
2278 COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT = gdkColor;
|
|
2279 }
|
|
2280
|
|
2281 /**
|
|
2282 * Returns a reasonable font for applications to use.
|
|
2283 * On some platforms, this will match the "default font"
|
|
2284 * or "system font" if such can be found. This font
|
|
2285 * should not be free'd because it was allocated by the
|
|
2286 * system, not the application.
|
|
2287 * <p>
|
|
2288 * Typically, applications which want the default look
|
|
2289 * should simply not set the font on the widgets they
|
|
2290 * create. Widgets are always created with the correct
|
|
2291 * default font for the class of user-interface component
|
|
2292 * they represent.
|
|
2293 * </p>
|
|
2294 *
|
|
2295 * @return a font
|
|
2296 *
|
|
2297 * @exception SWTException <ul>
|
|
2298 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
2299 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
2300 * </ul>
|
|
2301 */
|
|
2302 public override Font getSystemFont () {
|
|
2303 checkDevice ();
|
|
2304 if (systemFont !is null) return systemFont;
|
|
2305 auto style = OS.gtk_widget_get_style (shellHandle);
|
|
2306 auto defaultFont = OS.pango_font_description_copy (OS.gtk_style_get_font_desc (style));
|
|
2307 return systemFont = Font.gtk_new (this, defaultFont);
|
|
2308 }
|
|
2309
|
|
2310 /**
|
|
2311 * Returns the single instance of the system tray or null
|
|
2312 * when there is no system tray available for the platform.
|
|
2313 *
|
|
2314 * @return the system tray or <code>null</code>
|
|
2315 *
|
|
2316 * @exception SWTException <ul>
|
|
2317 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
2318 * </ul>
|
|
2319 *
|
|
2320 * @since 3.0
|
|
2321 */
|
|
2322 public Tray getSystemTray () {
|
|
2323 checkDevice ();
|
|
2324 if (tray !is null) return tray;
|
|
2325 return tray = new Tray (this, SWT.NONE);
|
|
2326 }
|
|
2327
|
|
2328 /**
|
|
2329 * Returns the user-interface thread for the receiver.
|
|
2330 *
|
|
2331 * @return the receiver's user-interface thread
|
|
2332 *
|
|
2333 * @exception SWTException <ul>
|
|
2334 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
2335 * </ul>
|
|
2336 */
|
|
2337 public Thread getThread () {
|
|
2338 synchronized (Device.classinfo) {
|
|
2339 if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
|
|
2340 return thread;
|
|
2341 }
|
|
2342 }
|
|
2343
|
|
2344 Widget getWidget (GtkWidget* handle) {
|
|
2345 if (handle is null) return null;
|
|
2346 if (lastWidget !is null && lastHandle is handle) return lastWidget;
|
|
2347 auto index = cast(int) OS.g_object_get_qdata ( cast(GObject*)handle, SWT_OBJECT_INDEX) - 1;
|
|
2348 if (0 <= index && index < widgetTable.length) {
|
|
2349 lastHandle = handle;
|
|
2350 return lastWidget = widgetTable [cast(int)/*64*/index];
|
|
2351 }
|
|
2352 return null;
|
|
2353 }
|
|
2354
|
|
2355 private static extern(C) int idleProcFunc (void* data) {
|
|
2356 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
2357 auto dbdata = cast(CallbackData*)data;
|
|
2358 return dbdata.display.idleProc();
|
|
2359 }
|
|
2360 private int idleProc () {
|
|
2361 bool result = runAsyncMessages (false);
|
|
2362 if (!result) {
|
|
2363 synchronized (idleLock) {
|
|
2364 idleHandle = 0;
|
|
2365 }
|
|
2366 }
|
|
2367 return result ? 1 : 0;
|
|
2368 return 0;
|
|
2369 }
|
|
2370
|
|
2371 /**
|
|
2372 * Initializes any internal resources needed by the
|
|
2373 * device.
|
|
2374 * <p>
|
|
2375 * This method is called after <code>create</code>.
|
|
2376 * </p>
|
|
2377 *
|
|
2378 * @see #create
|
|
2379 */
|
|
2380 protected override void init_ () {
|
|
2381 super.init_ ();
|
|
2382 initializeCallbacks ();
|
|
2383 initializeSystemColors ();
|
|
2384 initializeSystemSettings ();
|
|
2385 initializeWidgetTable ();
|
|
2386 initializeWindowManager ();
|
|
2387 }
|
|
2388
|
|
2389 void initializeCallbacks () {
|
|
2390 closures = new GClosure* [Widget.LAST_SIGNAL];
|
|
2391 signalIds = new int [Widget.LAST_SIGNAL];
|
|
2392
|
|
2393 /* Cache signals for GtkWidget */
|
|
2394 signalIds [Widget.BUTTON_PRESS_EVENT] = OS.g_signal_lookup (OS.button_press_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2395 signalIds [Widget.BUTTON_RELEASE_EVENT] = OS.g_signal_lookup (OS.button_release_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2396 signalIds [Widget.CONFIGURE_EVENT] = OS.g_signal_lookup (OS.configure_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2397 signalIds [Widget.DELETE_EVENT] = OS.g_signal_lookup (OS.delete_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2398 signalIds [Widget.ENTER_NOTIFY_EVENT] = OS.g_signal_lookup (OS.enter_notify_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2399 signalIds [Widget.EVENT] = OS.g_signal_lookup (OS.event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2400 signalIds [Widget.EVENT_AFTER] = OS.g_signal_lookup (OS.event_after.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2401 signalIds [Widget.EXPOSE_EVENT] = OS.g_signal_lookup (OS.expose_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2402 signalIds [Widget.FOCUS] = OS.g_signal_lookup (OS.focus.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2403 signalIds [Widget.FOCUS_IN_EVENT] = OS.g_signal_lookup (OS.focus_in_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2404 signalIds [Widget.FOCUS_OUT_EVENT] = OS.g_signal_lookup (OS.focus_out_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2405 signalIds [Widget.GRAB_FOCUS] = OS.g_signal_lookup (OS.grab_focus.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2406 signalIds [Widget.HIDE] = OS.g_signal_lookup (OS.hide.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2407 signalIds [Widget.KEY_PRESS_EVENT] = OS.g_signal_lookup (OS.key_press_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2408 signalIds [Widget.KEY_RELEASE_EVENT] = OS.g_signal_lookup (OS.key_release_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2409 signalIds [Widget.LEAVE_NOTIFY_EVENT] = OS.g_signal_lookup (OS.leave_notify_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2410 signalIds [Widget.MAP] = OS.g_signal_lookup (OS.map.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2411 signalIds [Widget.MAP_EVENT] = OS.g_signal_lookup (OS.map_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2412 signalIds [Widget.MNEMONIC_ACTIVATE] = OS.g_signal_lookup (OS.mnemonic_activate.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2413 signalIds [Widget.MOTION_NOTIFY_EVENT] = OS.g_signal_lookup (OS.motion_notify_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2414 signalIds [Widget.POPUP_MENU] = OS.g_signal_lookup (OS.popup_menu.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2415 signalIds [Widget.REALIZE] = OS.g_signal_lookup (OS.realize.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2416 signalIds [Widget.SCROLL_EVENT] = OS.g_signal_lookup (OS.scroll_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2417 signalIds [Widget.SHOW] = OS.g_signal_lookup (OS.show.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2418 signalIds [Widget.SHOW_HELP] = OS.g_signal_lookup (OS.show_help.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2419 signalIds [Widget.SIZE_ALLOCATE] = OS.g_signal_lookup (OS.size_allocate.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2420 signalIds [Widget.STYLE_SET] = OS.g_signal_lookup (OS.style_set.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2421 signalIds [Widget.UNMAP] = OS.g_signal_lookup (OS.unmap.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2422 signalIds [Widget.UNMAP_EVENT] = OS.g_signal_lookup (OS.unmap_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2423 signalIds [Widget.UNREALIZE] = OS.g_signal_lookup (OS.realize.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2424 signalIds [Widget.VISIBILITY_NOTIFY_EVENT] = OS.g_signal_lookup (OS.visibility_notify_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2425 signalIds [Widget.WINDOW_STATE_EVENT] = OS.g_signal_lookup (OS.window_state_event.ptr, OS.GTK_TYPE_WIDGET ());
|
|
2426
|
|
2427 GClosure* do_cclosure_new( GCallback cb, int value, int notify ){
|
|
2428 CallbackData* res= new CallbackData;
|
|
2429 res.display = this;
|
|
2430 res.data = cast(void*)value;
|
|
2431 windowProcCallbackDatas[ value ] = res;
|
|
2432 return OS.g_cclosure_new( cb, cast(void*)res, cast(GClosureNotify)notify );
|
|
2433 }
|
|
2434
|
|
2435 GCallback windowProc2 = cast(GCallback)&windowProcFunc2;
|
|
2436 closures [Widget.ACTIVATE] = do_cclosure_new (windowProc2, Widget.ACTIVATE, 0);
|
|
2437 closures [Widget.ACTIVATE_INVERSE] = do_cclosure_new (windowProc2, Widget.ACTIVATE_INVERSE, 0);
|
|
2438 closures [Widget.CHANGED] = do_cclosure_new (windowProc2, Widget.CHANGED, 0);
|
|
2439 closures [Widget.CLICKED] = do_cclosure_new (windowProc2, Widget.CLICKED, 0);
|
|
2440 closures [Widget.DAY_SELECTED] = do_cclosure_new (windowProc2, Widget.DAY_SELECTED, 0);
|
|
2441 closures [Widget.HIDE] = do_cclosure_new (windowProc2, Widget.HIDE, 0);
|
|
2442 closures [Widget.GRAB_FOCUS] = do_cclosure_new (windowProc2, Widget.GRAB_FOCUS, 0);
|
|
2443 closures [Widget.MAP] = do_cclosure_new (windowProc2, Widget.MAP, 0);
|
|
2444 closures [Widget.MONTH_CHANGED] = do_cclosure_new (windowProc2, Widget.MONTH_CHANGED, 0);
|
|
2445 closures [Widget.OUTPUT] = do_cclosure_new (windowProc2, Widget.OUTPUT, 0);
|
|
2446 closures [Widget.POPUP_MENU] = do_cclosure_new (windowProc2, Widget.POPUP_MENU, 0);
|
|
2447 closures [Widget.PREEDIT_CHANGED] = do_cclosure_new (windowProc2, Widget.PREEDIT_CHANGED, 0);
|
|
2448 closures [Widget.REALIZE] = do_cclosure_new (windowProc2, Widget.REALIZE, 0);
|
|
2449 closures [Widget.SELECT] = do_cclosure_new (windowProc2, Widget.SELECT, 0);
|
|
2450 closures [Widget.SHOW] = do_cclosure_new (windowProc2, Widget.SHOW, 0);
|
|
2451 closures [Widget.VALUE_CHANGED] = do_cclosure_new (windowProc2, Widget.VALUE_CHANGED, 0);
|
|
2452 closures [Widget.UNMAP] = do_cclosure_new (windowProc2, Widget.UNMAP, 0);
|
|
2453 closures [Widget.UNREALIZE] = do_cclosure_new (windowProc2, Widget.UNREALIZE, 0);
|
|
2454
|
|
2455 GCallback windowProc3 = cast(GCallback)&windowProcFunc3;
|
|
2456 closures [Widget.BUTTON_PRESS_EVENT] = do_cclosure_new (windowProc3, Widget.BUTTON_PRESS_EVENT, 0);
|
|
2457 closures [Widget.BUTTON_PRESS_EVENT_INVERSE] = do_cclosure_new (windowProc3, Widget.BUTTON_PRESS_EVENT_INVERSE, 0);
|
|
2458 closures [Widget.BUTTON_RELEASE_EVENT] = do_cclosure_new (windowProc3, Widget.BUTTON_RELEASE_EVENT, 0);
|
|
2459 closures [Widget.BUTTON_RELEASE_EVENT_INVERSE] = do_cclosure_new (windowProc3, Widget.BUTTON_RELEASE_EVENT_INVERSE, 0);
|
|
2460 closures [Widget.COMMIT] = do_cclosure_new (windowProc3, Widget.COMMIT, 0);
|
|
2461 closures [Widget.CONFIGURE_EVENT] = do_cclosure_new (windowProc3, Widget.CONFIGURE_EVENT, 0);
|
|
2462 closures [Widget.DELETE_EVENT] = do_cclosure_new (windowProc3, Widget.DELETE_EVENT, 0);
|
|
2463 closures [Widget.ENTER_NOTIFY_EVENT] = do_cclosure_new (windowProc3, Widget.ENTER_NOTIFY_EVENT, 0);
|
|
2464 closures [Widget.EVENT] = do_cclosure_new (windowProc3, Widget.EVENT, 0);
|
|
2465 closures [Widget.EVENT_AFTER] = do_cclosure_new (windowProc3, Widget.EVENT_AFTER, 0);
|
|
2466 closures [Widget.EXPOSE_EVENT] = do_cclosure_new (windowProc3, Widget.EXPOSE_EVENT, 0);
|
|
2467 closures [Widget.EXPOSE_EVENT_INVERSE] = do_cclosure_new (windowProc3, Widget.EXPOSE_EVENT_INVERSE, 0);
|
|
2468 closures [Widget.FOCUS] = do_cclosure_new (windowProc3, Widget.FOCUS, 0);
|
|
2469 closures [Widget.FOCUS_IN_EVENT] = do_cclosure_new (windowProc3, Widget.FOCUS_IN_EVENT, 0);
|
|
2470 closures [Widget.FOCUS_OUT_EVENT] = do_cclosure_new (windowProc3, Widget.FOCUS_OUT_EVENT, 0);
|
|
2471 closures [Widget.KEY_PRESS_EVENT] = do_cclosure_new (windowProc3, Widget.KEY_PRESS_EVENT, 0);
|
|
2472 closures [Widget.KEY_RELEASE_EVENT] = do_cclosure_new (windowProc3, Widget.KEY_RELEASE_EVENT, 0);
|
|
2473 closures [Widget.INPUT] = do_cclosure_new (windowProc3, Widget.INPUT, 0);
|
|
2474 closures [Widget.LEAVE_NOTIFY_EVENT] = do_cclosure_new (windowProc3, Widget.LEAVE_NOTIFY_EVENT, 0);
|
|
2475 closures [Widget.MAP_EVENT] = do_cclosure_new (windowProc3, Widget.MAP_EVENT, 0);
|
|
2476 closures [Widget.MNEMONIC_ACTIVATE] = do_cclosure_new (windowProc3, Widget.MNEMONIC_ACTIVATE, 0);
|
|
2477 closures [Widget.MOTION_NOTIFY_EVENT] = do_cclosure_new (windowProc3, Widget.MOTION_NOTIFY_EVENT, 0);
|
|
2478 closures [Widget.MOTION_NOTIFY_EVENT_INVERSE] = do_cclosure_new (windowProc3, Widget.MOTION_NOTIFY_EVENT_INVERSE, 0);
|
|
2479 closures [Widget.MOVE_FOCUS] = do_cclosure_new (windowProc3, Widget.MOVE_FOCUS, 0);
|
|
2480 closures [Widget.POPULATE_POPUP] = do_cclosure_new (windowProc3, Widget.POPULATE_POPUP, 0);
|
|
2481 closures [Widget.SCROLL_EVENT] = do_cclosure_new (windowProc3, Widget.SCROLL_EVENT, 0);
|
|
2482 closures [Widget.SHOW_HELP] = do_cclosure_new (windowProc3, Widget.SHOW_HELP, 0);
|
|
2483 closures [Widget.SIZE_ALLOCATE] = do_cclosure_new (windowProc3, Widget.SIZE_ALLOCATE, 0);
|
|
2484 closures [Widget.STYLE_SET] = do_cclosure_new (windowProc3, Widget.STYLE_SET, 0);
|
|
2485 closures [Widget.TOGGLED] = do_cclosure_new (windowProc3, Widget.TOGGLED, 0);
|
|
2486 closures [Widget.UNMAP_EVENT] = do_cclosure_new (windowProc3, Widget.UNMAP_EVENT, 0);
|
|
2487 closures [Widget.VISIBILITY_NOTIFY_EVENT] = do_cclosure_new (windowProc3, Widget.VISIBILITY_NOTIFY_EVENT, 0);
|
|
2488 closures [Widget.WINDOW_STATE_EVENT] = do_cclosure_new (windowProc3, Widget.WINDOW_STATE_EVENT, 0);
|
|
2489
|
|
2490 GCallback windowProc4 = cast(GCallback)&windowProcFunc4;
|
|
2491 closures [Widget.DELETE_RANGE] = do_cclosure_new (windowProc4, Widget.DELETE_RANGE, 0);
|
|
2492 closures [Widget.DELETE_TEXT] = do_cclosure_new (windowProc4, Widget.DELETE_TEXT, 0);
|
|
2493 closures [Widget.ROW_ACTIVATED] = do_cclosure_new (windowProc4, Widget.ROW_ACTIVATED, 0);
|
|
2494 closures [Widget.SCROLL_CHILD] = do_cclosure_new (windowProc4, Widget.SCROLL_CHILD, 0);
|
|
2495 closures [Widget.SWITCH_PAGE] = do_cclosure_new (windowProc4, Widget.SWITCH_PAGE, 0);
|
|
2496 closures [Widget.TEST_COLLAPSE_ROW] = do_cclosure_new (windowProc4, Widget.TEST_COLLAPSE_ROW, 0);
|
|
2497 closures [Widget.TEST_EXPAND_ROW] = do_cclosure_new (windowProc4, Widget.TEST_EXPAND_ROW, 0);
|
|
2498
|
|
2499 GCallback windowProc5 = cast(GCallback)&windowProcFunc5;
|
|
2500 closures [Widget.CHANGE_VALUE] = do_cclosure_new (windowProc5, Widget.CHANGE_VALUE, 0);
|
|
2501 closures [Widget.EXPAND_COLLAPSE_CURSOR_ROW] = do_cclosure_new (windowProc5, Widget.EXPAND_COLLAPSE_CURSOR_ROW, 0);
|
|
2502 closures [Widget.INSERT_TEXT] = do_cclosure_new (windowProc5, Widget.INSERT_TEXT, 0);
|
|
2503 closures [Widget.TEXT_BUFFER_INSERT_TEXT] = do_cclosure_new (windowProc5, Widget.TEXT_BUFFER_INSERT_TEXT, 0);
|
|
2504
|
|
2505 for (int i = 0; i < Widget.LAST_SIGNAL; i++) {
|
|
2506 if (closures [i] !is null) OS.g_closure_ref (closures [i]);
|
|
2507 }
|
|
2508 shellMapProcCallbackData.display = this;
|
|
2509 shellMapProcCallbackData.data = null;
|
|
2510 shellMapProcClosure = OS.g_cclosure_new (cast(GCallback)&shellMapProcFunc, &shellMapProcCallbackData, cast(GClosureNotify)0);
|
|
2511 OS.g_closure_ref (shellMapProcClosure);
|
|
2512 }
|
|
2513
|
|
2514 void* getWindowProcUserData( int value ){
|
|
2515 return windowProcCallbackDatas[ value ];
|
|
2516
|
|
2517 }
|
|
2518
|
|
2519 void initializeSystemSettings () {
|
|
2520 styleSetProcCallbackData.display = this;
|
|
2521 styleSetProcCallbackData.data = null;
|
|
2522 OS.g_signal_connect (shellHandle, OS.style_set.ptr, cast(GCallback)&styleSetProcFunc, &styleSetProcCallbackData);
|
|
2523
|
|
2524 /*
|
|
2525 * Feature in GTK. Despite the fact that the
|
|
2526 * gtk-entry-select-on-focus property is a global
|
|
2527 * setting, it is initialized when the GtkEntry
|
|
2528 * is initialized. This means that it cannot be
|
|
2529 * accessed before a GtkEntry is created. The
|
|
2530 * fix is to for the initializaion by creating
|
|
2531 * a temporary GtkEntry.
|
|
2532 */
|
|
2533 auto entry = OS.gtk_entry_new ();
|
|
2534 OS.gtk_widget_destroy (entry);
|
|
2535 int buffer2;
|
|
2536 auto settings = OS.gtk_settings_get_default ();
|
|
2537 OS.g_object_get1 (settings, OS.gtk_entry_select_on_focus.ptr, &buffer2);
|
|
2538 entrySelectOnFocus = buffer2 !is 0;
|
|
2539 }
|
|
2540
|
|
2541 void initializeWidgetTable () {
|
|
2542 indexTable = new int [GROW_SIZE];
|
|
2543 widgetTable = new Widget [GROW_SIZE];
|
|
2544 for (int i=0; i<GROW_SIZE-1; i++) indexTable [i] = i + 1;
|
|
2545 indexTable [GROW_SIZE - 1] = -1;
|
|
2546 }
|
|
2547
|
|
2548 void initializeWindowManager () {
|
|
2549 /* Get the window manager name */
|
|
2550 windowManager = ""; //$NON-NLS-1$
|
|
2551 if (OS.GTK_VERSION >= OS.buildVERSION (2, 2, 0)) {
|
|
2552 auto screen = OS.gdk_screen_get_default ();
|
|
2553 if (screen !is null) {
|
|
2554 auto ptr2 = OS.gdk_x11_screen_get_window_manager_name (screen);
|
|
2555 windowManager = fromStringz( ptr2 );
|
|
2556 }
|
|
2557 }
|
|
2558 }
|
|
2559
|
|
2560 /**
|
|
2561 * Invokes platform specific functionality to dispose a GC handle.
|
|
2562 * <p>
|
|
2563 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
|
|
2564 * API for <code>Display</code>. It is marked public only so that it
|
|
2565 * can be shared within the packages provided by SWT. It is not
|
|
2566 * available on all platforms, and should never be called from
|
|
2567 * application code.
|
|
2568 * </p>
|
|
2569 *
|
|
2570 * @param hDC the platform specific GC handle
|
|
2571 * @param data the platform specific GC data
|
|
2572 */
|
|
2573 public override void internal_dispose_GC (GdkGC* gdkGC, GCData data) {
|
|
2574 OS.g_object_unref (gdkGC);
|
|
2575 }
|
|
2576
|
|
2577 /**
|
|
2578 * Invokes platform specific functionality to allocate a new GC handle.
|
|
2579 * <p>
|
|
2580 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
|
|
2581 * API for <code>Display</code>. It is marked public only so that it
|
|
2582 * can be shared within the packages provided by SWT. It is not
|
|
2583 * available on all platforms, and should never be called from
|
|
2584 * application code.
|
|
2585 * </p>
|
|
2586 *
|
|
2587 * @param data the platform specific GC data
|
|
2588 * @return the platform specific GC handle
|
|
2589 *
|
|
2590 * @exception SWTException <ul>
|
|
2591 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
2592 * </ul>
|
|
2593 * @exception SWTError <ul>
|
|
2594 * <li>ERROR_NO_HANDLES if a handle could not be obtained for gc creation</li>
|
|
2595 * </ul>
|
|
2596 */
|
|
2597 public override GdkGC* internal_new_GC (GCData data) {
|
|
2598 if (isDisposed()) SWT.error(SWT.ERROR_DEVICE_DISPOSED);
|
|
2599 auto root = cast(GdkDrawable *) OS.GDK_ROOT_PARENT ();
|
|
2600 auto gdkGC = OS.gdk_gc_new (root);
|
|
2601 if (gdkGC is null) SWT.error (SWT.ERROR_NO_HANDLES);
|
|
2602 OS.gdk_gc_set_subwindow (gdkGC, OS.GDK_INCLUDE_INFERIORS);
|
|
2603 if (data !is null) {
|
|
2604 int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
|
|
2605 if ((data.style & mask) is 0) {
|
|
2606 data.style |= SWT.LEFT_TO_RIGHT;
|
|
2607 }
|
|
2608 data.device = this;
|
|
2609 data.drawable = root;
|
|
2610 data.background = getSystemColor (SWT.COLOR_WHITE).handle;
|
|
2611 data.foreground = getSystemColor (SWT.COLOR_BLACK).handle;
|
|
2612 data.font = getSystemFont ();
|
|
2613 }
|
|
2614 return gdkGC;
|
|
2615 return null;
|
|
2616 }
|
|
2617
|
|
2618 bool isValidThread () {
|
|
2619 return thread is Thread.getThis ();
|
|
2620 }
|
|
2621
|
|
2622 /**
|
|
2623 * Maps a point from one coordinate system to another.
|
|
2624 * When the control is null, coordinates are mapped to
|
|
2625 * the display.
|
|
2626 * <p>
|
|
2627 * NOTE: On right-to-left platforms where the coordinate
|
|
2628 * systems are mirrored, special care needs to be taken
|
|
2629 * when mapping coordinates from one control to another
|
|
2630 * to ensure the result is correctly mirrored.
|
|
2631 *
|
|
2632 * Mapping a point that is the origin of a rectangle and
|
|
2633 * then adding the width and height is not equivalent to
|
|
2634 * mapping the rectangle. When one control is mirrored
|
|
2635 * and the other is not, adding the width and height to a
|
|
2636 * point that was mapped causes the rectangle to extend
|
|
2637 * in the wrong direction. Mapping the entire rectangle
|
|
2638 * instead of just one point causes both the origin and
|
|
2639 * the corner of the rectangle to be mapped.
|
|
2640 * </p>
|
|
2641 *
|
|
2642 * @param from the source <code>Control</code> or <code>null</code>
|
|
2643 * @param to the destination <code>Control</code> or <code>null</code>
|
|
2644 * @param point to be mapped
|
|
2645 * @return point with mapped coordinates
|
|
2646 *
|
|
2647 * @exception IllegalArgumentException <ul>
|
|
2648 * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
|
|
2649 * <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
|
|
2650 * </ul>
|
|
2651 * @exception SWTException <ul>
|
|
2652 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
2653 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
2654 * </ul>
|
|
2655 *
|
|
2656 * @since 2.1.2
|
|
2657 */
|
|
2658 public Point map (Control from, Control to, Point point) {
|
|
2659 checkDevice ();
|
|
2660 if (point is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
2661 return map (from, to, point.x, point.y);
|
|
2662 }
|
|
2663
|
|
2664 /**
|
|
2665 * Maps a point from one coordinate system to another.
|
|
2666 * When the control is null, coordinates are mapped to
|
|
2667 * the display.
|
|
2668 * <p>
|
|
2669 * NOTE: On right-to-left platforms where the coordinate
|
|
2670 * systems are mirrored, special care needs to be taken
|
|
2671 * when mapping coordinates from one control to another
|
|
2672 * to ensure the result is correctly mirrored.
|
|
2673 *
|
|
2674 * Mapping a point that is the origin of a rectangle and
|
|
2675 * then adding the width and height is not equivalent to
|
|
2676 * mapping the rectangle. When one control is mirrored
|
|
2677 * and the other is not, adding the width and height to a
|
|
2678 * point that was mapped causes the rectangle to extend
|
|
2679 * in the wrong direction. Mapping the entire rectangle
|
|
2680 * instead of just one point causes both the origin and
|
|
2681 * the corner of the rectangle to be mapped.
|
|
2682 * </p>
|
|
2683 *
|
|
2684 * @param from the source <code>Control</code> or <code>null</code>
|
|
2685 * @param to the destination <code>Control</code> or <code>null</code>
|
|
2686 * @param x coordinates to be mapped
|
|
2687 * @param y coordinates to be mapped
|
|
2688 * @return point with mapped coordinates
|
|
2689 *
|
|
2690 * @exception IllegalArgumentException <ul>
|
|
2691 * <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
|
|
2692 * </ul>
|
|
2693 * @exception SWTException <ul>
|
|
2694 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
2695 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
2696 * </ul>
|
|
2697 *
|
|
2698 * @since 2.1.2
|
|
2699 */
|
|
2700 public Point map (Control from, Control to, int x, int y) {
|
|
2701 checkDevice ();
|
|
2702 if (from !is null && from.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
|
|
2703 if (to !is null && to.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
|
|
2704 Point point = new Point (x, y);
|
|
2705 if (from is to) return point;
|
|
2706 if (from !is null) {
|
|
2707 auto window = from.eventWindow ();
|
|
2708 int origin_x, origin_y;
|
|
2709 OS.gdk_window_get_origin (window, &origin_x, &origin_y);
|
|
2710 if ((from.style & SWT.MIRRORED) !is 0) point.x = from.getClientWidth () - point.x;
|
|
2711 point.x += origin_x;
|
|
2712 point.y += origin_y;
|
|
2713 }
|
|
2714 if (to !is null) {
|
|
2715 auto window = to.eventWindow ();
|
|
2716 int origin_x, origin_y;
|
|
2717 OS.gdk_window_get_origin (window, &origin_x, &origin_y);
|
|
2718 point.x -= origin_x;
|
|
2719 point.y -= origin_y;
|
|
2720 if ((to.style & SWT.MIRRORED) !is 0) point.x = to.getClientWidth () - point.x;
|
|
2721 }
|
|
2722 return point;
|
|
2723 }
|
|
2724
|
|
2725 /**
|
|
2726 * Maps a point from one coordinate system to another.
|
|
2727 * When the control is null, coordinates are mapped to
|
|
2728 * the display.
|
|
2729 * <p>
|
|
2730 * NOTE: On right-to-left platforms where the coordinate
|
|
2731 * systems are mirrored, special care needs to be taken
|
|
2732 * when mapping coordinates from one control to another
|
|
2733 * to ensure the result is correctly mirrored.
|
|
2734 *
|
|
2735 * Mapping a point that is the origin of a rectangle and
|
|
2736 * then adding the width and height is not equivalent to
|
|
2737 * mapping the rectangle. When one control is mirrored
|
|
2738 * and the other is not, adding the width and height to a
|
|
2739 * point that was mapped causes the rectangle to extend
|
|
2740 * in the wrong direction. Mapping the entire rectangle
|
|
2741 * instead of just one point causes both the origin and
|
|
2742 * the corner of the rectangle to be mapped.
|
|
2743 * </p>
|
|
2744 *
|
|
2745 * @param from the source <code>Control</code> or <code>null</code>
|
|
2746 * @param to the destination <code>Control</code> or <code>null</code>
|
|
2747 * @param rectangle to be mapped
|
|
2748 * @return rectangle with mapped coordinates
|
|
2749 *
|
|
2750 * @exception IllegalArgumentException <ul>
|
|
2751 * <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
|
|
2752 * <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
|
|
2753 * </ul>
|
|
2754 * @exception SWTException <ul>
|
|
2755 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
2756 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
2757 * </ul>
|
|
2758 *
|
|
2759 * @since 2.1.2
|
|
2760 */
|
|
2761 public Rectangle map (Control from, Control to, Rectangle rectangle) {
|
|
2762 checkDevice();
|
|
2763 if (rectangle is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
2764 return map (from, to, rectangle.x, rectangle.y, rectangle.width, rectangle.height);
|
|
2765 }
|
|
2766
|
|
2767 static wchar mbcsToWcs (wchar ch) {
|
|
2768 int key = ch & 0xFFFF;
|
|
2769 if (key <= 0x7F) return ch;
|
|
2770 char [] buffer;
|
|
2771 if (key <= 0xFF) {
|
|
2772 buffer = new char [1];
|
|
2773 buffer [0] = cast(char) key;
|
|
2774 } else {
|
|
2775 buffer = new char [2];
|
|
2776 buffer [0] = cast(char) ((key >> 8) & 0xFF);
|
|
2777 buffer [1] = cast(char) (key & 0xFF);
|
|
2778 }
|
|
2779 wchar [] result = Converter.mbcsToWcs (null, buffer);
|
|
2780 if (result.length is 0) return 0;
|
|
2781 return result [0];
|
|
2782 }
|
|
2783
|
|
2784
|
|
2785 package void doMenuPositionProc( GtkMenu* window, bool hasLocation ){
|
|
2786 /*
|
|
2787 * Bug in GTK. The timestamp passed into gtk_menu_popup is used
|
|
2788 * to perform an X pointer grab. It cannot be zero, else the grab
|
|
2789 * will fail. The fix is to ensure that the timestamp of the last
|
|
2790 * event processed is used.
|
|
2791 */
|
|
2792 OS.gtk_menu_popup (window, null, null,
|
|
2793 hasLocation ? &menuPositionProcFunc : null,
|
|
2794 cast(void*)this, 0, getLastEventTime() );
|
|
2795 }
|
|
2796
|
|
2797 private static extern(C) void menuPositionProcFunc (GtkMenu* menu, int* x, int* y, int* push_in, void* user_data) {
|
|
2798 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
2799 auto display = cast(Display)user_data;
|
|
2800 display.menuPositionProc( menu, x, y, push_in, null );
|
|
2801 }
|
|
2802
|
|
2803 void menuPositionProc (GtkMenu* menu, int* x, int* y, int* push_in, void* user_data) {
|
|
2804 Widget widget = getWidget (cast(GtkWidget*)menu);
|
|
2805 if (widget is null) return 0;
|
|
2806 widget.menuPositionProc (menu, x, y, push_in, user_data);
|
|
2807 }
|
|
2808
|
|
2809 /**
|
|
2810 * Maps a point from one coordinate system to another.
|
|
2811 * When the control is null, coordinates are mapped to
|
|
2812 * the display.
|
|
2813 * <p>
|
|
2814 * NOTE: On right-to-left platforms where the coordinate
|
|
2815 * systems are mirrored, special care needs to be taken
|
|
2816 * when mapping coordinates from one control to another
|
|
2817 * to ensure the result is correctly mirrored.
|
|
2818 *
|
|
2819 * Mapping a point that is the origin of a rectangle and
|
|
2820 * then adding the width and height is not equivalent to
|
|
2821 * mapping the rectangle. When one control is mirrored
|
|
2822 * and the other is not, adding the width and height to a
|
|
2823 * point that was mapped causes the rectangle to extend
|
|
2824 * in the wrong direction. Mapping the entire rectangle
|
|
2825 * instead of just one point causes both the origin and
|
|
2826 * the corner of the rectangle to be mapped.
|
|
2827 * </p>
|
|
2828 *
|
|
2829 * @param from the source <code>Control</code> or <code>null</code>
|
|
2830 * @param to the destination <code>Control</code> or <code>null</code>
|
|
2831 * @param x coordinates to be mapped
|
|
2832 * @param y coordinates to be mapped
|
|
2833 * @param width coordinates to be mapped
|
|
2834 * @param height coordinates to be mapped
|
|
2835 * @return rectangle with mapped coordinates
|
|
2836 *
|
|
2837 * @exception IllegalArgumentException <ul>
|
|
2838 * <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
|
|
2839 * </ul>
|
|
2840 * @exception SWTException <ul>
|
|
2841 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
2842 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
2843 * </ul>
|
|
2844 *
|
|
2845 * @since 2.1.2
|
|
2846 */
|
|
2847 public Rectangle map (Control from, Control to, int x, int y, int width, int height) {
|
|
2848 checkDevice();
|
|
2849 if (from !is null && from.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
|
|
2850 if (to !is null && to.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
|
|
2851 Rectangle rect = new Rectangle (x, y, width, height);
|
|
2852 if (from is to) return rect;
|
|
2853 bool fromRTL = false, toRTL = false;
|
|
2854 if (from !is null) {
|
|
2855 auto window = from.eventWindow ();
|
|
2856 int origin_x, origin_y;
|
|
2857 OS.gdk_window_get_origin (window, &origin_x, &origin_y);
|
|
2858 fromRTL = (from.style & SWT.MIRRORED) !is 0;
|
|
2859 if (fromRTL) rect.x = from.getClientWidth() - rect.x;
|
|
2860 rect.x += origin_x;
|
|
2861 rect.y += origin_y;
|
|
2862 }
|
|
2863 if (to !is null) {
|
|
2864 auto window = to.eventWindow ();
|
|
2865 int origin_x, origin_y;
|
|
2866 OS.gdk_window_get_origin (window, &origin_x, &origin_y);
|
|
2867 rect.x -= origin_x;
|
|
2868 rect.y -= origin_y;
|
|
2869 toRTL = (to.style & SWT.MIRRORED) !is 0;
|
|
2870 if (toRTL) rect.x = to.getClientWidth () - rect.x;
|
|
2871 }
|
|
2872 if (fromRTL !is toRTL) rect.x -= rect.width;
|
|
2873 return rect;
|
|
2874 }
|
|
2875
|
|
2876 private static extern(C) int /*long*/ mouseHoverProcFunc ( void* user_data) {
|
|
2877 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
2878 CallbackData* cbdata = cast(CallbackData*)user_data;
|
|
2879 return cbdata.display.mouseHoverProc( cast(GtkWidget*)cbdata.data );
|
|
2880 }
|
|
2881 int /*long*/ mouseHoverProc (GtkWidget* handle) {
|
|
2882 Widget widget = getWidget (handle);
|
|
2883 if (widget is null) return 0;
|
|
2884 return widget.hoverProc (handle);
|
|
2885 }
|
|
2886
|
|
2887 /**
|
|
2888 * Generate a low level system event.
|
|
2889 *
|
|
2890 * <code>post</code> is used to generate low level keyboard
|
|
2891 * and mouse events. The intent is to enable automated UI
|
|
2892 * testing by simulating the input from the user. Most
|
|
2893 * SWT applications should never need to call this method.
|
|
2894 * <p>
|
|
2895 * Note that this operation can fail when the operating system
|
|
2896 * fails to generate the event for any reason. For example,
|
|
2897 * this can happen when there is no such key or mouse button
|
|
2898 * or when the system event queue is full.
|
|
2899 * </p>
|
|
2900 * <p>
|
|
2901 * <b>Event Types:</b>
|
|
2902 * <p>KeyDown, KeyUp
|
|
2903 * <p>The following fields in the <code>Event</code> apply:
|
|
2904 * <ul>
|
|
2905 * <li>(in) type KeyDown or KeyUp</li>
|
|
2906 * <p> Either one of:
|
|
2907 * <li>(in) character a character that corresponds to a keyboard key</li>
|
|
2908 * <li>(in) keyCode the key code of the key that was typed,
|
|
2909 * as defined by the key code constants in class <code>SWT</code></li>
|
|
2910 * </ul>
|
|
2911 * <p>MouseDown, MouseUp</p>
|
|
2912 * <p>The following fields in the <code>Event</code> apply:
|
|
2913 * <ul>
|
|
2914 * <li>(in) type MouseDown or MouseUp
|
|
2915 * <li>(in) button the button that is pressed or released
|
|
2916 * </ul>
|
|
2917 * <p>MouseMove</p>
|
|
2918 * <p>The following fields in the <code>Event</code> apply:
|
|
2919 * <ul>
|
|
2920 * <li>(in) type MouseMove
|
|
2921 * <li>(in) x the x coordinate to move the mouse pointer to in screen coordinates
|
|
2922 * <li>(in) y the y coordinate to move the mouse pointer to in screen coordinates
|
|
2923 * </ul>
|
|
2924 * </dl>
|
|
2925 *
|
|
2926 * @param event the event to be generated
|
|
2927 *
|
|
2928 * @return true if the event was generated or false otherwise
|
|
2929 *
|
|
2930 * @exception IllegalArgumentException <ul>
|
|
2931 * <li>ERROR_NULL_ARGUMENT - if the event is null</li>
|
|
2932 * </ul>
|
|
2933 * @exception SWTException <ul>
|
|
2934 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
2935 * </ul>
|
|
2936 *
|
|
2937 * @since 3.0
|
|
2938 *
|
|
2939 */
|
|
2940 public bool post (Event event) {
|
|
2941 synchronized (Device.classinfo) {
|
|
2942 if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
|
|
2943 if (event is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
2944 if (!OS.GDK_WINDOWING_X11()) return false;
|
|
2945 auto xDisplay = OS.GDK_DISPLAY ();
|
|
2946 int type = event.type;
|
|
2947 switch (type) {
|
|
2948 case SWT.KeyDown:
|
|
2949 case SWT.KeyUp: {
|
|
2950 int keyCode = 0;
|
|
2951 auto keysym = untranslateKey (event.keyCode);
|
|
2952 if (keysym !is 0) keyCode = OS.XKeysymToKeycode (xDisplay, keysym);
|
|
2953 if (keyCode is 0) {
|
|
2954 char key = event.character;
|
|
2955 switch (key) {
|
|
2956 case SWT.BS: keysym = OS.GDK_BackSpace; break;
|
|
2957 case SWT.CR: keysym = OS.GDK_Return; break;
|
|
2958 case SWT.DEL: keysym = OS.GDK_Delete; break;
|
|
2959 case SWT.ESC: keysym = OS.GDK_Escape; break;
|
|
2960 case SWT.TAB: keysym = OS.GDK_Tab; break;
|
|
2961 case SWT.LF: keysym = OS.GDK_Linefeed; break;
|
|
2962 default:
|
|
2963 keysym = key;
|
|
2964 }
|
|
2965 keyCode = OS.XKeysymToKeycode (xDisplay, keysym);
|
|
2966 if (keyCode is 0) return false;
|
|
2967 }
|
|
2968 OS.XTestFakeKeyEvent (xDisplay, keyCode, type is SWT.KeyDown, 0);
|
|
2969 return true;
|
|
2970 }
|
|
2971 case SWT.MouseDown:
|
|
2972 case SWT.MouseMove:
|
|
2973 case SWT.MouseUp: {
|
|
2974 if (type is SWT.MouseMove) {
|
|
2975 OS.XTestFakeMotionEvent (xDisplay, -1, event.x, event.y, 0);
|
|
2976 } else {
|
|
2977 int button = event.button;
|
|
2978 switch (button) {
|
|
2979 case 1:
|
|
2980 case 2:
|
|
2981 case 3: break;
|
|
2982 case 4: button = 6; break;
|
|
2983 case 5: button = 7; break;
|
|
2984 default: return false;
|
|
2985 }
|
|
2986 OS.XTestFakeButtonEvent (xDisplay, button, type is SWT.MouseDown, 0);
|
|
2987 }
|
|
2988 return true;
|
|
2989 default:
|
|
2990 }
|
|
2991 /*
|
|
2992 * This code is intentionally commented. After posting a
|
|
2993 * mouse wheel event the system may respond unpredictably
|
|
2994 * to subsequent mouse actions.
|
|
2995 */
|
|
2996 // case SWT.MouseWheel: {
|
|
2997 // if (event.count is 0) return false;
|
|
2998 // int button = event.count < 0 ? 5 : 4;
|
|
2999 // OS.XTestFakeButtonEvent (xDisplay, button, type is SWT.MouseWheel, 0);
|
|
3000 // }
|
|
3001 }
|
|
3002 return false;
|
|
3003 }
|
|
3004 }
|
|
3005
|
|
3006 void postEvent (Event event) {
|
|
3007 /*
|
|
3008 * Place the event at the end of the event queue.
|
|
3009 * This code is always called in the Display's
|
|
3010 * thread so it must be re-enterant but does not
|
|
3011 * need to be synchronized.
|
|
3012 */
|
|
3013 if (eventQueue is null) eventQueue = new Event [4];
|
|
3014 int index = 0;
|
|
3015 int length = eventQueue.length;
|
|
3016 while (index < length) {
|
|
3017 if (eventQueue [index] is null) break;
|
|
3018 index++;
|
|
3019 }
|
|
3020 if (index is length) {
|
|
3021 Event [] newQueue = new Event [length + 4];
|
|
3022 System.arraycopy (eventQueue, 0, newQueue, 0, length);
|
|
3023 eventQueue = newQueue;
|
|
3024 }
|
|
3025 eventQueue [index] = event;
|
|
3026 }
|
|
3027
|
|
3028 void putGdkEvents () {
|
|
3029 if (gdkEventCount !is 0) {
|
|
3030 for (int i = 0; i < gdkEventCount; i++) {
|
|
3031 auto event = gdkEvents [i];
|
|
3032 Widget widget = gdkEventWidgets [i];
|
|
3033 if (widget is null || !widget.isDisposed ()) {
|
|
3034 OS.gdk_event_put (event);
|
|
3035 }
|
|
3036 OS.gdk_event_free (event);
|
|
3037 gdkEvents [i] = null;
|
|
3038 gdkEventWidgets [i] = null;
|
|
3039 }
|
|
3040 gdkEventCount = 0;
|
|
3041 }
|
|
3042 }
|
|
3043
|
|
3044 /**
|
|
3045 * Reads an event from the operating system's event queue,
|
|
3046 * dispatches it appropriately, and returns <code>true</code>
|
|
3047 * if there is potentially more work to do, or <code>false</code>
|
|
3048 * if the caller can sleep until another event is placed on
|
|
3049 * the event queue.
|
|
3050 * <p>
|
|
3051 * In addition to checking the system event queue, this method also
|
|
3052 * checks if any inter-thread messages (created by <code>syncExec()</code>
|
|
3053 * or <code>asyncExec()</code>) are waiting to be processed, and if
|
|
3054 * so handles them before returning.
|
|
3055 * </p>
|
|
3056 *
|
|
3057 * @return <code>false</code> if the caller can sleep upon return from this method
|
|
3058 *
|
|
3059 * @exception SWTException <ul>
|
|
3060 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
3061 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
3062 * <li>ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message</li>
|
|
3063 * </ul>
|
|
3064 *
|
|
3065 * @see #sleep
|
|
3066 * @see #wake
|
|
3067 */
|
|
3068 public bool readAndDispatch () {
|
|
3069 checkDevice ();
|
|
3070 bool events = false;
|
|
3071 events |= runSettings ();
|
|
3072 events |= runPopups ();
|
|
3073 events |= cast(bool)OS.g_main_context_iteration (null, false);
|
|
3074 if (events) {
|
|
3075 runDeferredEvents ();
|
|
3076 return true;
|
|
3077 }
|
|
3078 return runAsyncMessages (false);
|
|
3079 }
|
|
3080
|
|
3081 static void register (Display display) {
|
|
3082 synchronized (Device.classinfo) {
|
|
3083 for (int i=0; i<Displays.length; i++) {
|
|
3084 if (Displays [i] is null) {
|
|
3085 Displays [i] = display;
|
|
3086 return;
|
|
3087 }
|
|
3088 }
|
|
3089 Display [] newDisplays = new Display [Displays.length + 4];
|
|
3090 System.arraycopy (Displays, 0, newDisplays, 0, Displays.length);
|
|
3091 newDisplays [Displays.length] = display;
|
|
3092 Displays = newDisplays;
|
|
3093 }
|
|
3094 }
|
|
3095
|
|
3096 /**
|
|
3097 * Releases any internal resources back to the operating
|
|
3098 * system and clears all fields except the device handle.
|
|
3099 * <p>
|
|
3100 * Disposes all shells which are currently open on the display.
|
|
3101 * After this method has been invoked, all related related shells
|
|
3102 * will answer <code>true</code> when sent the message
|
|
3103 * <code>isDisposed()</code>.
|
|
3104 * </p><p>
|
|
3105 * When a device is destroyed, resources that were acquired
|
|
3106 * on behalf of the programmer need to be returned to the
|
|
3107 * operating system. For example, if the device allocated a
|
|
3108 * font to be used as the system font, this font would be
|
|
3109 * freed in <code>release</code>. Also,to assist the garbage
|
|
3110 * collector and minimize the amount of memory that is not
|
|
3111 * reclaimed when the programmer keeps a reference to a
|
|
3112 * disposed device, all fields except the handle are zero'd.
|
|
3113 * The handle is needed by <code>destroy</code>.
|
|
3114 * </p>
|
|
3115 * This method is called before <code>destroy</code>.
|
|
3116 *
|
|
3117 * @see Device#dispose
|
|
3118 * @see #destroy
|
|
3119 */
|
|
3120 protected override void release () {
|
|
3121 sendEvent (SWT.Dispose, new Event ());
|
|
3122 Shell [] shells = getShells ();
|
|
3123 for (int i=0; i<shells.length; i++) {
|
|
3124 Shell shell = shells [i];
|
|
3125 if (!shell.isDisposed ()) shell.dispose ();
|
|
3126 }
|
|
3127 if (tray !is null) tray.dispose ();
|
|
3128 tray = null;
|
|
3129 while (readAndDispatch ()) {}
|
|
3130 if (disposeList !is null) {
|
|
3131 for (int i=0; i<disposeList.length; i++) {
|
|
3132 if (disposeList [i] !is null) disposeList [i].run ();
|
|
3133 }
|
|
3134 }
|
|
3135 disposeList = null;
|
|
3136 synchronizer.releaseSynchronizer ();
|
|
3137 synchronizer = null;
|
|
3138 releaseDisplay ();
|
|
3139 super.release ();
|
|
3140 }
|
|
3141
|
|
3142 void releaseDisplay () {
|
|
3143
|
|
3144 /* Dispose xfilter callback */
|
|
3145 OS.gdk_window_remove_filter(null, &filterProcFunc, null);
|
|
3146
|
|
3147 /* Dispose checkIfEvent callback */
|
|
3148
|
|
3149 /* Dispose preedit window */
|
|
3150 if (preeditWindow !is null) OS.gtk_widget_destroy ( &preeditWindow.bin.container.widget);
|
|
3151 imControl = null;
|
|
3152
|
|
3153 /* Dispose the menu callback */
|
|
3154
|
|
3155 /* Dispose the tooltip map callback */
|
|
3156
|
|
3157 /* Dispose the shell map callback */
|
|
3158
|
|
3159 /* Dispose the run async messages callback */
|
|
3160 if (idleHandle !is 0) OS.g_source_remove (idleHandle);
|
|
3161 idleHandle = 0;
|
|
3162
|
|
3163 /* Dispose GtkTreeView callbacks */
|
|
3164
|
|
3165 /* Dispose the set direction callback */
|
|
3166
|
|
3167 /* Dispose the emission proc callback */
|
|
3168
|
|
3169 /* Dispose the set direction callback */
|
|
3170
|
|
3171 /* Dispose the caret callback */
|
|
3172 if (caretId !is 0) OS.gtk_timeout_remove (caretId);
|
|
3173 caretId = 0;
|
|
3174
|
|
3175 /* Release closures */
|
|
3176 for (int i = 0; i < Widget.LAST_SIGNAL; i++) {
|
|
3177 if (closures [i] !is null) OS.g_closure_unref (closures [i]);
|
|
3178 }
|
|
3179 if (shellMapProcClosure !is null) OS.g_closure_unref (shellMapProcClosure);
|
|
3180
|
|
3181 /* Dispose the timer callback */
|
|
3182 if (timerIds !is null) {
|
|
3183 for (int i=0; i<timerIds.length; i++) {
|
|
3184 if (timerIds [i] !is 0) OS.gtk_timeout_remove (timerIds [i]);
|
|
3185 }
|
|
3186 }
|
|
3187 timerIds = null;
|
|
3188 timerList = null;
|
|
3189
|
|
3190 /* Dispose mouse hover callback */
|
|
3191 if (mouseHoverId !is 0) OS.gtk_timeout_remove (mouseHoverId);
|
|
3192 mouseHoverId = 0;
|
|
3193 mouseHoverHandle = null;
|
|
3194
|
|
3195 /* Dispose the default font */
|
|
3196 if (systemFont !is null) systemFont.dispose ();
|
|
3197 systemFont = null;
|
|
3198
|
|
3199 /* Dispose the System Images */
|
|
3200 if (errorImage !is null) errorImage.dispose();
|
|
3201 if (infoImage !is null) infoImage.dispose();
|
|
3202 if (questionImage !is null) questionImage.dispose();
|
|
3203 if (warningImage !is null) warningImage.dispose();
|
|
3204 errorImage = infoImage = questionImage = warningImage = null;
|
|
3205
|
|
3206 /* Release the System Cursors */
|
|
3207 for (int i = 0; i < cursors.length; i++) {
|
|
3208 if (cursors [i] !is null) cursors [i].dispose ();
|
|
3209 }
|
|
3210 cursors = null;
|
|
3211
|
|
3212 /* Release Acquired Resources */
|
|
3213 if (resources !is null) {
|
|
3214 for (int i=0; i<resources.length; i++) {
|
|
3215 if (resources [i] !is null) resources [i].dispose ();
|
|
3216 }
|
|
3217 resources = null;
|
|
3218 }
|
|
3219
|
|
3220 /* Release the System Colors */
|
|
3221 COLOR_WIDGET_DARK_SHADOW = COLOR_WIDGET_NORMAL_SHADOW = COLOR_WIDGET_LIGHT_SHADOW =
|
|
3222 COLOR_WIDGET_HIGHLIGHT_SHADOW = COLOR_WIDGET_BACKGROUND = COLOR_WIDGET_BORDER =
|
|
3223 COLOR_LIST_FOREGROUND = COLOR_LIST_BACKGROUND = COLOR_LIST_SELECTION = COLOR_LIST_SELECTION_TEXT =
|
|
3224 COLOR_WIDGET_FOREGROUND = COLOR_TITLE_FOREGROUND = COLOR_TITLE_BACKGROUND = COLOR_TITLE_BACKGROUND_GRADIENT =
|
|
3225 COLOR_TITLE_INACTIVE_FOREGROUND = COLOR_TITLE_INACTIVE_BACKGROUND = COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT =
|
|
3226 COLOR_INFO_BACKGROUND = COLOR_INFO_FOREGROUND = null;
|
|
3227
|
|
3228 /* Dispose the event callback */
|
|
3229 OS.gdk_event_handler_set (null, null, null);
|
|
3230
|
|
3231 /* Dispose the hidden shell */
|
|
3232 if (shellHandle !is null) OS.gtk_widget_destroy (shellHandle);
|
|
3233 shellHandle = null;
|
|
3234
|
|
3235 /* Dispose the settings callback */
|
|
3236
|
|
3237 /* Release the sleep resources */
|
|
3238 max_priority = 0;
|
|
3239 timeout = 0;
|
|
3240 if (fds !is null) OS.g_free (fds.ptr);
|
|
3241 fds = null;
|
|
3242
|
|
3243 /* Release references */
|
|
3244 popups = null;
|
|
3245 thread = null;
|
|
3246 lastWidget = activeShell = null;
|
|
3247 //flushData = null;
|
|
3248 closures = null;
|
|
3249 indexTable = signalIds = treeSelection = null;
|
|
3250 widgetTable = modalShells = null;
|
|
3251 data = null;
|
|
3252 values = null;
|
|
3253 keys = null;
|
|
3254 windowManager = null;
|
|
3255 eventTable = filterTable = null;
|
|
3256 modalDialog = null;
|
|
3257 flushRect = null;
|
|
3258 exposeEvent = null;
|
|
3259 visibilityEvent = null;
|
|
3260 idleLock = null;
|
|
3261 }
|
|
3262
|
|
3263 /**
|
|
3264 * Removes the listener from the collection of listeners who will
|
|
3265 * be notified when an event of the given type occurs anywhere in
|
|
3266 * a widget. The event type is one of the event constants defined
|
|
3267 * in class <code>SWT</code>.
|
|
3268 *
|
|
3269 * @param eventType the type of event to listen for
|
|
3270 * @param listener the listener which should no longer be notified when the event occurs
|
|
3271 *
|
|
3272 * @exception IllegalArgumentException <ul>
|
|
3273 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
|
|
3274 * </ul>
|
|
3275 * @exception SWTException <ul>
|
|
3276 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
3277 * </ul>
|
|
3278 *
|
|
3279 * @see Listener
|
|
3280 * @see SWT
|
|
3281 * @see #addFilter
|
|
3282 * @see #addListener
|
|
3283 *
|
|
3284 * @since 3.0
|
|
3285 */
|
|
3286 public void removeFilter (int eventType, Listener listener) {
|
|
3287 checkDevice ();
|
|
3288 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
3289 if (filterTable is null) return;
|
|
3290 filterTable.unhook (eventType, listener);
|
|
3291 if (filterTable.size () is 0) filterTable = null;
|
|
3292 }
|
|
3293
|
|
3294 GdkEvent* removeGdkEvent () {
|
|
3295 if (gdkEventCount is 0) return null;
|
|
3296 auto event = gdkEvents [0];
|
|
3297 --gdkEventCount;
|
|
3298 SimpleType!(GdkEvent*).arraycopy (gdkEvents, 1, gdkEvents, 0, gdkEventCount);
|
|
3299 System.arraycopy (gdkEventWidgets, 1, gdkEventWidgets, 0, gdkEventCount);
|
|
3300 gdkEvents [gdkEventCount] = null;
|
|
3301 gdkEventWidgets [gdkEventCount] = null;
|
|
3302 if (gdkEventCount is 0) {
|
|
3303 gdkEvents = null;
|
|
3304 gdkEventWidgets = null;
|
|
3305 }
|
|
3306 return event;
|
|
3307 }
|
|
3308
|
|
3309 void removeIdleProc () {
|
|
3310 synchronized (idleLock) {
|
|
3311 if (idleHandle !is 0) OS.g_source_remove (idleHandle);
|
|
3312 idleNeeded = false;
|
|
3313 idleHandle = 0;
|
|
3314 }
|
|
3315 }
|
|
3316 /**
|
|
3317 * Removes the listener from the collection of listeners who will
|
|
3318 * be notified when an event of the given type occurs. The event type
|
|
3319 * is one of the event constants defined in class <code>SWT</code>.
|
|
3320 *
|
|
3321 * @param eventType the type of event to listen for
|
|
3322 * @param listener the listener which should no longer be notified
|
|
3323 *
|
|
3324 * @exception IllegalArgumentException <ul>
|
|
3325 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
|
|
3326 * </ul>
|
|
3327 * @exception SWTException <ul>
|
|
3328 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
3329 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
3330 * </ul>
|
|
3331 *
|
|
3332 * @see Listener
|
|
3333 * @see SWT
|
|
3334 * @see #addListener
|
|
3335 *
|
|
3336 * @since 2.0
|
|
3337 */
|
|
3338 public void removeListener (int eventType, Listener listener) {
|
|
3339 checkDevice ();
|
|
3340 if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
3341 if (eventTable is null) return;
|
|
3342 eventTable.unhook (eventType, listener);
|
|
3343 }
|
|
3344
|
|
3345 void removeMouseHoverTimeout (void* handle) {
|
|
3346 if (handle !is mouseHoverHandle) return;
|
|
3347 if (mouseHoverId !is 0) OS.gtk_timeout_remove (mouseHoverId);
|
|
3348 mouseHoverId = 0;
|
|
3349 mouseHoverHandle = null;
|
|
3350 }
|
|
3351
|
|
3352 void removePopup (Menu menu) {
|
|
3353 if (popups is null) return;
|
|
3354 for (int i=0; i<popups.length; i++) {
|
|
3355 if (popups [i] is menu) {
|
|
3356 popups [i] = null;
|
|
3357 return;
|
|
3358 }
|
|
3359 }
|
|
3360 }
|
|
3361
|
|
3362 Widget removeWidget (GtkWidget* handle) {
|
|
3363 if (handle is null) return null;
|
|
3364 lastWidget = null;
|
|
3365 Widget widget = null;
|
|
3366 int index = cast(int)/*64*/ OS.g_object_get_qdata (cast(GObject*)handle, SWT_OBJECT_INDEX) - 1;
|
|
3367 if (0 <= index && index < widgetTable.length) {
|
|
3368 widget = widgetTable [index];
|
|
3369 widgetTable [index] = null;
|
|
3370 indexTable [index] = freeSlot;
|
|
3371 freeSlot = index;
|
|
3372 OS.g_object_set_qdata (cast(GObject*)handle, SWT_OBJECT_INDEX, null);
|
|
3373 }
|
|
3374 return widget;
|
|
3375 }
|
|
3376
|
|
3377 bool runAsyncMessages (bool all) {
|
|
3378 return synchronizer.runAsyncMessages (all);
|
|
3379 }
|
|
3380
|
|
3381 bool runDeferredEvents () {
|
|
3382 /*
|
|
3383 * Run deferred events. This code is always
|
|
3384 * called in the Display's thread so it must
|
|
3385 * be re-enterant but need not be synchronized.
|
|
3386 */
|
|
3387 while (eventQueue !is null) {
|
|
3388
|
|
3389 /* Take an event off the queue */
|
|
3390 Event event = eventQueue [0];
|
|
3391 if (event is null) break;
|
|
3392 int len = eventQueue.length;
|
|
3393 System.arraycopy (eventQueue, 1, eventQueue, 0, --len);
|
|
3394 eventQueue [len] = null;
|
|
3395
|
|
3396 /* Run the event */
|
|
3397 Widget widget = event.widget;
|
|
3398 if (widget !is null && !widget.isDisposed ()) {
|
|
3399 Widget item = event.item;
|
|
3400 if (item is null || !item.isDisposed ()) {
|
|
3401 widget.sendEvent (event);
|
|
3402 }
|
|
3403 }
|
|
3404
|
|
3405 /*
|
|
3406 * At this point, the event queue could
|
|
3407 * be null due to a recursive invokation
|
|
3408 * when running the event.
|
|
3409 */
|
|
3410 }
|
|
3411
|
|
3412 /* Clear the queue */
|
|
3413 eventQueue = null;
|
|
3414 return true;
|
|
3415 }
|
|
3416
|
|
3417 bool runPopups () {
|
|
3418 if (popups is null) return false;
|
|
3419 bool result = false;
|
|
3420 while (popups !is null) {
|
|
3421 Menu menu = popups [0];
|
|
3422 if (menu is null) break;
|
|
3423 int len = popups.length;
|
|
3424 System.arraycopy (popups, 1, popups, 0, --len);
|
|
3425 popups [len] = null;
|
|
3426 runDeferredEvents ();
|
|
3427 if (!menu.isDisposed ()) menu._setVisible (true);
|
|
3428 result = true;
|
|
3429 }
|
|
3430 popups = null;
|
|
3431 return result;
|
|
3432 }
|
|
3433
|
|
3434 bool runSettings () {
|
|
3435 if (!runSettingsFld) return false;
|
|
3436 runSettingsFld = false;
|
|
3437 saveResources ();
|
|
3438 initializeSystemColors ();
|
|
3439 sendEvent (SWT.Settings, null);
|
|
3440 Shell [] shells = getShells ();
|
|
3441 for (int i=0; i<shells.length; i++) {
|
|
3442 Shell shell = shells [i];
|
|
3443 if (!shell.isDisposed ()) {
|
|
3444 shell.fixStyle ();
|
|
3445 shell.redraw (true);
|
|
3446 shell.layout (true, true);
|
|
3447 }
|
|
3448 }
|
|
3449 return true;
|
|
3450 }
|
|
3451
|
|
3452 /**
|
|
3453 * On platforms which support it, sets the application name
|
|
3454 * to be the argument. On Motif, for example, this can be used
|
|
3455 * to set the name used for resource lookup. Specifying
|
|
3456 * <code>null</code> for the name clears it.
|
|
3457 *
|
|
3458 * @param name the new app name or <code>null</code>
|
|
3459 */
|
|
3460 public static void setAppName (String name) {
|
|
3461 APP_NAME = name;
|
|
3462 }
|
|
3463
|
|
3464 /**
|
|
3465 * Sets the location of the on-screen pointer relative to the top left corner
|
|
3466 * of the screen. <b>Note: It is typically considered bad practice for a
|
|
3467 * program to move the on-screen pointer location.</b>
|
|
3468 *
|
|
3469 * @param x the new x coordinate for the cursor
|
|
3470 * @param y the new y coordinate for the cursor
|
|
3471 *
|
|
3472 * @exception SWTException <ul>
|
|
3473 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
3474 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
3475 * </ul>
|
|
3476 *
|
|
3477 * @since 2.1
|
|
3478 */
|
|
3479 public void setCursorLocation (int x, int y) {
|
|
3480 checkDevice ();
|
|
3481 if (OS.GDK_WINDOWING_X11 ()) {
|
|
3482 auto xDisplay = OS.GDK_DISPLAY ();
|
|
3483 auto xWindow = OS.XDefaultRootWindow (xDisplay);
|
|
3484 OS.XWarpPointer (xDisplay, OS.None, xWindow, 0, 0, 0, 0, x, y);
|
|
3485 }
|
|
3486 }
|
|
3487
|
|
3488 /**
|
|
3489 * Sets the location of the on-screen pointer relative to the top left corner
|
|
3490 * of the screen. <b>Note: It is typically considered bad practice for a
|
|
3491 * program to move the on-screen pointer location.</b>
|
|
3492 *
|
|
3493 * @param point new position
|
|
3494 *
|
|
3495 * @exception SWTException <ul>
|
|
3496 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
3497 * <li>ERROR_NULL_ARGUMENT - if the point is null
|
|
3498 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
3499 * </ul>
|
|
3500 *
|
|
3501 * @since 2.0
|
|
3502 */
|
|
3503 public void setCursorLocation (Point point) {
|
|
3504 checkDevice ();
|
|
3505 if (point is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
3506 setCursorLocation (point.x, point.y);
|
|
3507 }
|
|
3508
|
|
3509 /**
|
|
3510 * Sets the application defined property of the receiver
|
|
3511 * with the specified name to the given argument.
|
|
3512 * <p>
|
|
3513 * Applications may have associated arbitrary objects with the
|
|
3514 * receiver in this fashion. If the objects stored in the
|
|
3515 * properties need to be notified when the display is disposed
|
|
3516 * of, it is the application's responsibility provide a
|
|
3517 * <code>disposeExec()</code> handler which does so.
|
|
3518 * </p>
|
|
3519 *
|
|
3520 * @param key the name of the property
|
|
3521 * @param value the new value for the property
|
|
3522 *
|
|
3523 * @exception SWTException <ul>
|
|
3524 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
3525 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
3526 * </ul>
|
|
3527 *
|
|
3528 * @see #getData(String)
|
|
3529 * @see #disposeExec(Runnable)
|
|
3530 */
|
|
3531 public void setData (String key, Object value) {
|
|
3532 checkDevice ();
|
|
3533 // SWT extension: allow null for zero length string
|
|
3534 //if (key is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
3535
|
|
3536 if (key.equals (DISPATCH_EVENT_KEY)) {
|
|
3537 ArrayWrapperInt wrappedValue;
|
|
3538 if (value is null || (null !is (wrappedValue=cast(ArrayWrapperInt)value))) {
|
|
3539 dispatchEvents = wrappedValue.array;
|
|
3540 if (value is null) putGdkEvents ();
|
|
3541 return;
|
|
3542 }
|
|
3543 }
|
|
3544 if (key.equals (SET_MODAL_DIALOG)) {
|
|
3545 setModalDialog (cast(Dialog) data);
|
|
3546 return;
|
|
3547 }
|
|
3548
|
|
3549 if (key.equals (ADD_WIDGET_KEY)) {
|
|
3550 auto wrap = cast(ArrayWrapperObject) value;
|
|
3551 if( wrap is null ) SWT.error(SWT.ERROR_INVALID_ARGUMENT, null, " []");
|
|
3552 Object [] data = wrap.array;
|
|
3553 auto handle = (cast(LONG) data [0]).value;
|
|
3554 Widget widget = cast(Widget) data [1];
|
|
3555 if (widget !is null) {
|
|
3556 addWidget (cast(GtkWidget*)handle, widget);
|
|
3557 } else {
|
|
3558 removeWidget (cast(GtkWidget*)handle);
|
|
3559 }
|
|
3560 }
|
|
3561
|
|
3562 if (key==/*eq*/ ADD_IDLE_PROC_KEY) {
|
|
3563 addIdleProc ();
|
|
3564 return;
|
|
3565 }
|
|
3566 if (key==/*eq*/ REMOVE_IDLE_PROC_KEY) {
|
|
3567 removeIdleProc ();
|
|
3568 return;
|
|
3569 }
|
|
3570
|
|
3571 /* Remove the key/value pair */
|
|
3572 if (value is null) {
|
|
3573 if (keys is null) return;
|
|
3574 int index = 0;
|
|
3575 while (index < keys.length && keys [index]!=/*!eq*/ key) index++;
|
|
3576 if (index is keys.length) return;
|
|
3577 if (keys.length is 1) {
|
|
3578 keys = null;
|
|
3579 values = null;
|
|
3580 } else {
|
|
3581 String [] newKeys = new String [keys.length - 1];
|
|
3582 Object [] newValues = new Object [values.length - 1];
|
|
3583 System.arraycopy (keys, 0, newKeys, 0, index);
|
|
3584 System.arraycopy (keys, index + 1, newKeys, index, newKeys.length - index);
|
|
3585 System.arraycopy (values, 0, newValues, 0, index);
|
|
3586 System.arraycopy (values, index + 1, newValues, index, newValues.length - index);
|
|
3587 keys = newKeys;
|
|
3588 values = newValues;
|
|
3589 }
|
|
3590 return;
|
|
3591 }
|
|
3592
|
|
3593 /* Add the key/value pair */
|
|
3594 if (keys is null) {
|
|
3595 keys = [key];
|
|
3596 values = [value];
|
|
3597 return;
|
|
3598 }
|
|
3599 for (int i=0; i<keys.length; i++) {
|
|
3600 if (keys [i]==/*eq*/ key) {
|
|
3601 values [i] = value;
|
|
3602 return;
|
|
3603 }
|
|
3604 }
|
|
3605 String [] newKeys = new String [keys.length + 1];
|
|
3606 Object [] newValues = new Object [values.length + 1];
|
|
3607 System.arraycopy (keys, 0, newKeys, 0, keys.length);
|
|
3608 System.arraycopy (values, 0, newValues, 0, values.length);
|
|
3609 newKeys [keys.length] = key;
|
|
3610 newValues [values.length] = value;
|
|
3611 keys = newKeys;
|
|
3612 values = newValues;
|
|
3613 }
|
|
3614
|
|
3615 /**
|
|
3616 * Sets the application defined, display specific data
|
|
3617 * associated with the receiver, to the argument.
|
|
3618 * The <em>display specific data</em> is a single,
|
|
3619 * unnamed field that is stored with every display.
|
|
3620 * <p>
|
|
3621 * Applications may put arbitrary objects in this field. If
|
|
3622 * the object stored in the display specific data needs to
|
|
3623 * be notified when the display is disposed of, it is the
|
|
3624 * application's responsibility provide a
|
|
3625 * <code>disposeExec()</code> handler which does so.
|
|
3626 * </p>
|
|
3627 *
|
|
3628 * @param data the new display specific data
|
|
3629 *
|
|
3630 * @exception SWTException <ul>
|
|
3631 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
3632 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
3633 * </ul>
|
|
3634 *
|
|
3635 * @see #getData()
|
|
3636 * @see #disposeExec(Runnable)
|
|
3637 */
|
|
3638 public void setData (Object data) {
|
|
3639 checkDevice ();
|
|
3640 this.data = data;
|
|
3641 }
|
|
3642
|
|
3643
|
|
3644 void doSetDirectionProc( GtkWidget* widget, int direction ){
|
|
3645 setDirectionProcCallbackData.display = this;
|
|
3646 setDirectionProcCallbackData.data = cast(void*)direction;
|
|
3647 OS.gtk_container_forall (cast(GtkContainer*)widget, cast(GtkCallback)&setDirectionProcFunc, &setDirectionProcCallbackData);
|
|
3648 }
|
|
3649
|
|
3650 package static extern(C) int /*long*/ setDirectionProcFunc (GtkWidget* widget, void* data) {
|
|
3651 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
3652 CallbackData* cbdata = cast(CallbackData*)data;
|
|
3653 return cbdata.display.setDirectionProc( widget, cast(int)cbdata.data );
|
|
3654 }
|
|
3655 int /*long*/ setDirectionProc (GtkWidget* widget, int /*long*/ direction) {
|
|
3656 OS.gtk_widget_set_direction (widget, direction);
|
|
3657 if (OS.GTK_IS_MENU_ITEM (widget)) {
|
|
3658 auto submenu = OS.gtk_menu_item_get_submenu (widget);
|
|
3659 if (submenu !is null) {
|
|
3660 OS.gtk_widget_set_direction (submenu, cast(int)/*64*/ direction);
|
|
3661 OS.gtk_container_forall (cast(GtkContainer*)submenu, cast(GtkCallback)&setDirectionProcFunc, cast(void*)direction);
|
|
3662 }
|
|
3663 }
|
|
3664 if (OS.GTK_IS_CONTAINER (cast(GTypeInstance*)widget)) {
|
|
3665 OS.gtk_container_forall (cast(GtkContainer*)widget, cast(GtkCallback)&setDirectionProcFunc, cast(void*)direction);
|
|
3666 }
|
|
3667 return 0;
|
|
3668 }
|
|
3669
|
|
3670 void setModalDialog (Dialog modalDailog) {
|
|
3671 this.modalDialog = modalDailog;
|
|
3672 Shell [] shells = getShells ();
|
|
3673 for (int i=0; i<shells.length; i++) shells [i].updateModal ();
|
|
3674 }
|
|
3675
|
|
3676 void setModalShell (Shell shell) {
|
|
3677 if (modalShells is null) modalShells = new Shell [4];
|
|
3678 int index = 0, length = modalShells.length;
|
|
3679 while (index < length) {
|
|
3680 if (modalShells [index] is shell) return;
|
|
3681 if (modalShells [index] is null) break;
|
|
3682 index++;
|
|
3683 }
|
|
3684 if (index is length) {
|
|
3685 Shell [] newModalShells = new Shell [length + 4];
|
|
3686 System.arraycopy (modalShells, 0, newModalShells, 0, length);
|
|
3687 modalShells = newModalShells;
|
|
3688 }
|
|
3689 modalShells [index] = shell;
|
|
3690 Shell [] shells = getShells ();
|
|
3691 for (int i=0; i<shells.length; i++) shells [i].updateModal ();
|
|
3692 }
|
|
3693
|
|
3694 /**
|
|
3695 * Sets the synchronizer used by the display to be
|
|
3696 * the argument, which can not be null.
|
|
3697 *
|
|
3698 * @param synchronizer the new synchronizer for the display (must not be null)
|
|
3699 *
|
|
3700 * @exception IllegalArgumentException <ul>
|
|
3701 * <li>ERROR_NULL_ARGUMENT - if the synchronizer is null</li>
|
|
3702 * </ul>
|
|
3703 * @exception SWTException <ul>
|
|
3704 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
3705 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
3706 * <li>ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message</li>
|
|
3707 * </ul>
|
|
3708 */
|
|
3709 public void setSynchronizer (Synchronizer synchronizer) {
|
|
3710 checkDevice ();
|
|
3711 if (synchronizer is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
3712 if (synchronizer is this.synchronizer) return;
|
|
3713 Synchronizer oldSynchronizer;
|
|
3714 synchronized (Device.classinfo) {
|
|
3715 oldSynchronizer = this.synchronizer;
|
|
3716 this.synchronizer = synchronizer;
|
|
3717 }
|
|
3718 if (oldSynchronizer !is null) {
|
|
3719 oldSynchronizer.runAsyncMessages(true);
|
|
3720 }
|
|
3721 }
|
|
3722
|
|
3723 void showIMWindow (Control control) {
|
|
3724 imControl = control;
|
|
3725 if (preeditWindow is null) {
|
|
3726 preeditWindow = cast(GtkWindow*)OS.gtk_window_new (OS.GTK_WINDOW_POPUP);
|
|
3727 if (preeditWindow is null) error (SWT.ERROR_NO_HANDLES);
|
|
3728 preeditLabel = cast(GtkLabel*) OS.gtk_label_new (null);
|
|
3729 if (preeditLabel is null) error (SWT.ERROR_NO_HANDLES);
|
|
3730 OS.gtk_container_add (cast(GtkContainer*)preeditWindow, cast(GtkWidget*) preeditLabel);
|
|
3731 OS.gtk_widget_show (cast(GtkWidget*)preeditLabel);
|
|
3732 }
|
|
3733 char* preeditString;
|
|
3734 PangoAttrList* pangoAttrs;
|
|
3735 auto imHandle = control.imHandle ();
|
|
3736 OS.gtk_im_context_get_preedit_string (imHandle, &preeditString, &pangoAttrs, null);
|
|
3737 if (preeditString !is null && strlen (preeditString) > 0) {
|
|
3738 Control widget = control.findBackgroundControl ();
|
|
3739 if (widget is null) widget = control;
|
|
3740 OS.gtk_widget_modify_bg (cast(GtkWidget*)preeditWindow, OS.GTK_STATE_NORMAL, widget.getBackgroundColor ());
|
|
3741 widget.setForegroundColor (cast(GtkWidget*)preeditLabel, control.getForegroundColor());
|
|
3742 OS.gtk_widget_modify_font (cast(GtkWidget*)preeditLabel, control.getFontDescription ());
|
|
3743 if (pangoAttrs !is null) OS.gtk_label_set_attributes (preeditLabel, pangoAttrs);
|
|
3744 OS.gtk_label_set_text (preeditLabel, preeditString);
|
|
3745 Point point = control.toDisplay (control.getIMCaretPos ());
|
|
3746 OS.gtk_window_move (preeditWindow, point.x, point.y);
|
|
3747 GtkRequisition requisition;
|
|
3748 OS.gtk_widget_size_request (cast(GtkWidget*)preeditLabel, &requisition);
|
|
3749 OS.gtk_window_resize (preeditWindow, requisition.width, requisition.height);
|
|
3750 OS.gtk_widget_show (cast(GtkWidget*)preeditWindow);
|
|
3751 } else {
|
|
3752 OS.gtk_widget_hide (cast(GtkWidget*)preeditWindow);
|
|
3753 }
|
|
3754 if (preeditString !is null) OS.g_free (preeditString);
|
|
3755 if (pangoAttrs !is null) OS.pango_attr_list_unref (pangoAttrs);
|
|
3756 }
|
|
3757
|
|
3758 /**
|
|
3759 * Causes the user-interface thread to <em>sleep</em> (that is,
|
|
3760 * to be put in a state where it does not consume CPU cycles)
|
|
3761 * until an event is received or it is otherwise awakened.
|
|
3762 *
|
|
3763 * @return <code>true</code> if an event requiring dispatching was placed on the queue.
|
|
3764 *
|
|
3765 * @exception SWTException <ul>
|
|
3766 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
3767 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
3768 * </ul>
|
|
3769 *
|
|
3770 * @see #wake
|
|
3771 */
|
|
3772 public bool sleep () {
|
|
3773 checkDevice ();
|
|
3774 if (gdkEventCount is 0) {
|
|
3775 gdkEvents = null;
|
|
3776 gdkEventWidgets = null;
|
|
3777 }
|
|
3778 if (settingsChanged) {
|
|
3779 settingsChanged = false;
|
|
3780 runSettingsFld = true;
|
|
3781 return false;
|
|
3782 }
|
|
3783 if (getMessageCount () !is 0) return true;
|
|
3784 if (fds is null) {
|
|
3785 allocated_nfds = 2;
|
|
3786 GPollFD* ptr = cast(GPollFD*) OS.g_malloc( GPollFD.sizeof * allocated_nfds );
|
|
3787 fds = ptr[ 0 .. allocated_nfds ];
|
|
3788 }
|
|
3789 max_priority = timeout = 0;
|
|
3790 auto context = OS.g_main_context_default ();
|
|
3791 bool result = false;
|
|
3792 do {
|
|
3793 if (OS.g_main_context_acquire (context)) {
|
|
3794 result = cast(bool)OS.g_main_context_prepare (context, &max_priority);
|
|
3795 int nfds;
|
|
3796 while ((nfds = OS.g_main_context_query (context, max_priority, &timeout, fds.ptr, allocated_nfds)) > allocated_nfds) {
|
|
3797 OS.g_free (fds.ptr);
|
|
3798 allocated_nfds = nfds;
|
|
3799 GPollFD* ptr = cast(GPollFD*) OS.g_malloc( GPollFD.sizeof * allocated_nfds );
|
|
3800 fds = ptr[ 0 .. allocated_nfds ];
|
|
3801 }
|
|
3802 GPollFunc poll = OS.g_main_context_get_poll_func (context);
|
|
3803 if (poll !is null) {
|
|
3804 if (nfds > 0 || timeout !is 0) {
|
|
3805 /*
|
|
3806 * Bug in GTK. For some reason, g_main_context_wakeup() may
|
|
3807 * fail to wake up the UI thread from the polling function.
|
|
3808 * The fix is to sleep for a maximum of 50 milliseconds.
|
|
3809 */
|
|
3810 if (timeout < 0) timeout = 50;
|
|
3811
|
|
3812 /* Exit the OS lock to allow other threads to enter GTK */
|
|
3813 Lock lock = OS.lock;
|
|
3814 int count = lock.lock ();
|
|
3815 for (int i = 0; i < count; i++) lock.unlock ();
|
|
3816 try {
|
|
3817 wake_state = false;
|
|
3818 poll( fds.ptr, nfds, timeout);
|
|
3819 } finally {
|
|
3820 for (int i = 0; i < count; i++) lock.lock ();
|
|
3821 lock.unlock ();
|
|
3822 }
|
|
3823 }
|
|
3824 }
|
|
3825 OS.g_main_context_check (context, max_priority, fds.ptr, nfds);
|
|
3826 OS.g_main_context_release (context);
|
|
3827 }
|
|
3828 } while (!result && getMessageCount () is 0 && !wake_state);
|
|
3829 wake_state = false;
|
|
3830 return true;
|
|
3831 }
|
|
3832
|
|
3833 /**
|
|
3834 * Causes the <code>run()</code> method of the runnable to
|
|
3835 * be invoked by the user-interface thread after the specified
|
|
3836 * number of milliseconds have elapsed. If milliseconds is less
|
|
3837 * than zero, the runnable is not executed.
|
|
3838 * <p>
|
|
3839 * Note that at the time the runnable is invoked, widgets
|
|
3840 * that have the receiver as their display may have been
|
|
3841 * disposed. Therefore, it is necessary to check for this
|
|
3842 * case inside the runnable before accessing the widget.
|
|
3843 * </p>
|
|
3844 *
|
|
3845 * @param milliseconds the delay before running the runnable
|
|
3846 * @param runnable code to run on the user-interface thread
|
|
3847 *
|
|
3848 * @exception IllegalArgumentException <ul>
|
|
3849 * <li>ERROR_NULL_ARGUMENT - if the runnable is null</li>
|
|
3850 * </ul>
|
|
3851 * @exception SWTException <ul>
|
|
3852 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
3853 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
3854 * </ul>
|
|
3855 *
|
|
3856 * @see #asyncExec
|
|
3857 */
|
|
3858 public void timerExec (int milliseconds, Runnable runnable) {
|
|
3859 checkDevice ();
|
|
3860 if (runnable is null) error (SWT.ERROR_NULL_ARGUMENT);
|
|
3861 if (timerList is null) timerList = new Runnable [4];
|
|
3862 if (timerIds is null) timerIds = new int [4];
|
|
3863 int index = 0;
|
|
3864 while (index < timerList.length) {
|
|
3865 if (timerList [index] is runnable) break;
|
|
3866 index++;
|
|
3867 }
|
|
3868 if (index !is timerList.length) {
|
|
3869 OS.gtk_timeout_remove (timerIds [index]);
|
|
3870 timerList [index] = null;
|
|
3871 timerIds [index] = 0;
|
|
3872 if (milliseconds < 0) return;
|
|
3873 } else {
|
|
3874 if (milliseconds < 0) return;
|
|
3875 index = 0;
|
|
3876 while (index < timerList.length) {
|
|
3877 if (timerList [index] is null) break;
|
|
3878 index++;
|
|
3879 }
|
|
3880 if (index is timerList.length) {
|
|
3881 Runnable [] newTimerList = new Runnable [timerList.length + 4];
|
|
3882 SimpleType!(Runnable).arraycopy (timerList, 0, newTimerList, 0, timerList.length);
|
|
3883 timerList = newTimerList;
|
|
3884 int [] newTimerIds = new int [timerIds.length + 4];
|
|
3885 System.arraycopy (timerIds, 0, newTimerIds, 0, timerIds.length);
|
|
3886 timerIds = newTimerIds;
|
|
3887 }
|
|
3888 }
|
|
3889 timerProcCallbackData.display = this;
|
|
3890 timerProcCallbackData.data = cast(void*)index;
|
|
3891 int timerId = OS.gtk_timeout_add (milliseconds, &timerProcFunc, &timerProcCallbackData);
|
|
3892 if (timerId !is 0) {
|
|
3893 timerIds [index] = timerId;
|
|
3894 timerList [index] = runnable;
|
|
3895 }
|
|
3896 }
|
|
3897
|
|
3898
|
|
3899 private static extern(C) int timerProcFunc ( void * data ) {
|
|
3900 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
3901 CallbackData* cbdata = cast( CallbackData* ) data;
|
|
3902 return cbdata.display.timerProc( cast(int) cbdata.data );
|
|
3903 }
|
|
3904
|
|
3905 int /*long*/ timerProc (int /*long*/ i) {
|
|
3906 if (timerList is null) return 0;
|
|
3907 int index = cast(int)/*64*/i;
|
|
3908 if (0 <= index && index < timerList.length) {
|
|
3909 Runnable runnable = timerList [index];
|
|
3910 timerList [index] = null;
|
|
3911 timerIds [index] = 0;
|
|
3912 if (runnable !is null) runnable.run ();
|
|
3913 }
|
|
3914 return 0;
|
|
3915 }
|
|
3916
|
|
3917 private static extern(C) int caretProcFunc ( void * data ) {
|
|
3918 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
3919 CallbackData* cbdata = cast( CallbackData* ) data;
|
|
3920 return cbdata.display.caretProc( cast(int) cbdata.data );
|
|
3921 }
|
|
3922 int /*long*/ caretProc (int /*long*/ clientData) {
|
|
3923 caretId = 0;
|
|
3924 if (currentCaret is null) {
|
|
3925 return 0;
|
|
3926 }
|
|
3927 if (currentCaret.blinkCaret()) {
|
|
3928 int blinkRate = currentCaret.blinkRate;
|
|
3929 if (blinkRate is 0) return 0;
|
|
3930 caretProcCallbackData.display = this;
|
|
3931 caretProcCallbackData.data = cast(void*)0;
|
|
3932 caretId = OS.gtk_timeout_add (blinkRate, &caretProcFunc, &caretProcCallbackData);
|
|
3933 } else {
|
|
3934 currentCaret = null;
|
|
3935 }
|
|
3936 return 0;
|
|
3937 }
|
|
3938
|
|
3939
|
|
3940 package int doSizeAllocateConnect( CallbackData* cbdata, GtkWidget* window, GtkWidget* widget ){
|
|
3941 cbdata.display = this;
|
|
3942 cbdata.data = cast(void*)widget;
|
|
3943 return OS.g_signal_connect (cast(void*)window, OS.size_allocate.ptr, cast(GCallback)&sizeAllocateProcFunc, cast(void*)&cbdata);
|
|
3944 }
|
|
3945
|
|
3946 private static extern(C) void sizeAllocateProcFunc (GtkWidget* handle, int /*long*/ arg0, int /*long*/ user_data) {
|
|
3947 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
3948 auto cbdata = cast(CallbackData*)user_data;
|
|
3949 cbdata.display.sizeAllocateProc( cast(GtkWidget*)handle, arg0, cast(int)cbdata.data );
|
|
3950 }
|
|
3951
|
|
3952 void sizeAllocateProc (GtkWidget* handle, int /*long*/ arg0, int /*long*/ user_data) {
|
|
3953 Widget widget = getWidget ( cast(GtkWidget*)user_data);
|
|
3954 if (widget is null) return 0;
|
|
3955 widget.sizeAllocateProc (handle, arg0, user_data);
|
|
3956 }
|
|
3957
|
|
3958
|
|
3959 package int doSizeRequestConnect( CallbackData* cbdata, GtkWidget* window, GtkWidget* widget ){
|
|
3960 cbdata.display = this;
|
|
3961 cbdata.data = cast(void*)widget;
|
|
3962 return OS.g_signal_connect (cast(void*)window, OS.size_request.ptr, cast(GCallback)&sizeRequestProcFunc, cast(void*)&cbdata );
|
|
3963 }
|
|
3964
|
|
3965 private static extern(C) void sizeRequestProcFunc (GtkWidget* handle, int /*long*/ arg0, int /*long*/ user_data) {
|
|
3966 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
3967 auto cbdata = cast(CallbackData*)user_data;
|
|
3968 cbdata.display.sizeRequestProcMeth( cast(GtkWidget*)handle, arg0, cast(int)cbdata.data );
|
|
3969 }
|
|
3970
|
|
3971 int /*long*/ sizeRequestProcMeth (GtkWidget* handle, int /*long*/ arg0, int /*long*/ user_data) {
|
|
3972 Widget widget = getWidget (cast(GtkWidget*)user_data);
|
|
3973 if (widget is null) return 0;
|
|
3974 return widget.sizeRequestProc (handle, arg0, user_data);
|
|
3975 }
|
|
3976
|
|
3977 package void doTreeSelectionProcConnect( CallbackData* cbdata, GtkWidget* widget, GtkTreeSelection* selection ){
|
|
3978 cbdata.display = this;
|
|
3979 cbdata.data = cast(void*)widget;
|
|
3980 OS.gtk_tree_selection_selected_foreach (selection, &treeSelectionProcFunc, widget);
|
|
3981 }
|
|
3982
|
|
3983 private static extern(C) void treeSelectionProcFunc (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, void* data) {
|
|
3984 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
3985 auto cbdata = cast(CallbackData*)data;
|
|
3986 cbdata.display.treeSelectionProcMeth( model, path, iter, cbdata.data );
|
|
3987 }
|
|
3988
|
|
3989 void treeSelectionProcMeth (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, void* data) {
|
|
3990 Widget widget = getWidget (cast(GtkWidget*)data);
|
|
3991 if (widget is null) return 0;
|
|
3992 widget.treeSelectionProc (model, path, iter, treeSelection, treeSelectionLength++);
|
|
3993 }
|
|
3994
|
|
3995 void saveResources () {
|
|
3996 int resourceCount = 0;
|
|
3997 if (resources is null) {
|
|
3998 resources = new Resource [RESOURCE_SIZE];
|
|
3999 } else {
|
|
4000 resourceCount = resources.length;
|
|
4001 Resource [] newResources = new Resource [resourceCount + RESOURCE_SIZE];
|
|
4002 System.arraycopy (resources, 0, newResources, 0, resourceCount);
|
|
4003 resources = newResources;
|
|
4004 }
|
|
4005 if (systemFont !is null) {
|
|
4006 resources [resourceCount++] = systemFont;
|
|
4007 systemFont = null;
|
|
4008 }
|
|
4009 if (errorImage !is null) resources [resourceCount++] = errorImage;
|
|
4010 if (infoImage !is null) resources [resourceCount++] = infoImage;
|
|
4011 if (questionImage !is null) resources [resourceCount++] = questionImage;
|
|
4012 if (warningImage !is null) resources [resourceCount++] = warningImage;
|
|
4013 errorImage = infoImage = questionImage = warningImage = null;
|
|
4014 for (int i=0; i<cursors.length; i++) {
|
|
4015 if (cursors [i] !is null) resources [resourceCount++] = cursors [i];
|
|
4016 cursors [i] = null;
|
|
4017 }
|
|
4018 if (resourceCount < RESOURCE_SIZE) {
|
|
4019 Resource [] newResources = new Resource [resourceCount];
|
|
4020 System.arraycopy (resources, 0, newResources, 0, resourceCount);
|
|
4021 resources = newResources;
|
|
4022 }
|
|
4023 }
|
|
4024
|
|
4025 void sendEvent (int eventType, Event event) {
|
|
4026 if (eventTable is null && filterTable is null) {
|
|
4027 return;
|
|
4028 }
|
|
4029 if (event is null) event = new Event ();
|
|
4030 event.display = this;
|
|
4031 event.type = eventType;
|
|
4032 if (event.time is 0) event.time = getLastEventTime ();
|
|
4033 if (!filterEvent (event)) {
|
|
4034 if (eventTable !is null) eventTable.sendEvent (event);
|
|
4035 }
|
|
4036 }
|
|
4037
|
|
4038 void setCurrentCaret (Caret caret) {
|
|
4039 if (caretId !is 0) OS.gtk_timeout_remove(caretId);
|
|
4040 caretId = 0;
|
|
4041 currentCaret = caret;
|
|
4042 if (caret is null) return;
|
|
4043 int blinkRate = currentCaret.blinkRate;
|
|
4044 caretProcCallbackData.display = this;
|
|
4045 caretProcCallbackData.data = cast(void*)0;
|
|
4046 caretId = OS.gtk_timeout_add (blinkRate, &caretProcFunc, &caretProcCallbackData);
|
|
4047 }
|
|
4048
|
|
4049 private static extern(C) int /*long*/ shellMapProcFunc (int /*long*/ handle, int /*long*/ arg0, int /*long*/ user_data) {
|
|
4050 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
4051 auto cbdata = cast(CallbackData*)user_data;
|
|
4052 return cbdata.display.shellMapProc( cast(GtkWidget*)handle, arg0, cast(int)cbdata.data );
|
|
4053 }
|
|
4054
|
|
4055 int /*long*/ shellMapProc (GtkWidget* handle, int /*long*/ arg0, int /*long*/ user_data) {
|
|
4056 Widget widget = getWidget (cast(GtkWidget*)handle);
|
|
4057 if (widget is null) return 0;
|
|
4058 return widget.shellMapProc (handle, arg0, user_data);
|
|
4059 }
|
|
4060
|
|
4061 private static extern(C) int /*long*/ styleSetProcFunc (int /*long*/ gobject, int /*long*/ arg1, int /*long*/ user_data) {
|
|
4062 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
4063 auto cbdata = cast(CallbackData*)user_data;
|
|
4064 return cbdata.display.styleSetProcMeth( gobject, arg1, cast(int)cbdata.data );
|
|
4065 }
|
|
4066 int /*long*/ styleSetProcMeth (int /*long*/ gobject, int /*long*/ arg1, int /*long*/ user_data) {
|
|
4067 settingsChanged = true;
|
|
4068 return 0;
|
|
4069 }
|
|
4070
|
|
4071 /**
|
|
4072 * Causes the <code>run()</code> method of the runnable to
|
|
4073 * be invoked by the user-interface thread at the next
|
|
4074 * reasonable opportunity. The thread which calls this method
|
|
4075 * is suspended until the runnable completes. Specifying <code>null</code>
|
|
4076 * as the runnable simply wakes the user-interface thread.
|
|
4077 * <p>
|
|
4078 * Note that at the time the runnable is invoked, widgets
|
|
4079 * that have the receiver as their display may have been
|
|
4080 * disposed. Therefore, it is necessary to check for this
|
|
4081 * case inside the runnable before accessing the widget.
|
|
4082 * </p>
|
|
4083 *
|
|
4084 * @param runnable code to run on the user-interface thread or <code>null</code>
|
|
4085 *
|
|
4086 * @exception SWTException <ul>
|
|
4087 * <li>ERROR_FAILED_EXEC - if an exception occurred when executing the runnable</li>
|
|
4088 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
4089 * </ul>
|
|
4090 *
|
|
4091 * @see #asyncExec
|
|
4092 */
|
|
4093 public void syncExec (Runnable runnable) {
|
|
4094 Synchronizer synchronizer;
|
|
4095 synchronized (Device.classinfo) {
|
|
4096 if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
|
|
4097 synchronizer = this.synchronizer;
|
|
4098 synchronized (idleLock) {
|
|
4099 if (idleNeeded && idleHandle is 0) {
|
|
4100 //NOTE: calling unlocked function in OS
|
|
4101 idleProcCallbackData.display = this;
|
|
4102 idleProcCallbackData.data = cast(void*)0;
|
|
4103 //PORTING_TODO: was _g_idle_add, calling directly
|
|
4104 idleHandle = OS.g_idle_add (&idleProcFunc, &idleProcCallbackData);
|
|
4105 }
|
|
4106 }
|
|
4107 }
|
|
4108 synchronizer.syncExec (runnable);
|
|
4109 }
|
|
4110
|
|
4111 static int translateKey (int key) {
|
|
4112 for (int i=0; i<KeyTable.length; i++) {
|
|
4113 if (KeyTable [i] [0] is key) return KeyTable [i] [1];
|
|
4114 }
|
|
4115 return 0;
|
|
4116 }
|
|
4117
|
|
4118 static int untranslateKey (int key) {
|
|
4119 for (int i=0; i<KeyTable.length; i++) {
|
|
4120 if (KeyTable [i] [1] is key) return KeyTable [i] [0];
|
|
4121 }
|
|
4122 return 0;
|
|
4123 }
|
|
4124
|
|
4125 /**
|
|
4126 * Forces all outstanding paint requests for the display
|
|
4127 * to be processed before this method returns.
|
|
4128 *
|
|
4129 * @exception SWTException <ul>
|
|
4130 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
|
|
4131 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
4132 * </ul>
|
|
4133 *
|
|
4134 * @see Control#update()
|
|
4135 */
|
|
4136 public void update () {
|
|
4137 checkDevice ();
|
|
4138 flushExposes (null, true);
|
|
4139 OS.gdk_window_process_all_updates ();
|
|
4140 }
|
|
4141
|
|
4142 /**
|
|
4143 * If the receiver's user-interface thread was <code>sleep</code>ing,
|
|
4144 * causes it to be awakened and start running again. Note that this
|
|
4145 * method may be called from any thread.
|
|
4146 *
|
|
4147 * @exception SWTException <ul>
|
|
4148 * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
|
|
4149 * </ul>
|
|
4150 *
|
|
4151 * @see #sleep
|
|
4152 */
|
|
4153 public void wake () {
|
|
4154 synchronized (Device.classinfo) {
|
|
4155 if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
|
|
4156 if (thread is Thread.getThis ()) return;
|
|
4157 wakeThread ();
|
|
4158 }
|
|
4159 }
|
|
4160
|
|
4161 void wakeThread () {
|
|
4162 OS.g_main_context_wakeup (null);
|
|
4163 wake_state = true;
|
|
4164 }
|
|
4165
|
|
4166 static dchar wcsToMbcs (char ch) {
|
|
4167 //PORTING_TODO not sure about this
|
|
4168 int key = ch & 0xFFFF;
|
|
4169 if (key <= 0x7F) return ch;
|
|
4170 char [] buffer = Converter.wcsToMbcs (null,[ch], false);
|
|
4171 if (buffer.length is 1) return '\0';
|
|
4172 if (buffer.length is 2) {
|
|
4173 return cast(char) (((buffer [0] & 0xFF) << 8) | (buffer [1] & 0xFF));
|
|
4174 }
|
|
4175 return '\0';
|
|
4176 }
|
|
4177
|
|
4178 private static extern(C) int /*long*/ windowProcFunc2 (GtkWidget* handle, int /*long*/ user_data) {
|
|
4179 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
4180 CallbackData* cbdata = cast(CallbackData*)user_data;
|
|
4181 return cbdata.display.windowProc( handle, cast(int)cbdata.data );
|
|
4182 }
|
|
4183 int /*long*/ windowProc (GtkWidget* handle, int /*long*/ user_data) {
|
|
4184 Widget widget = getWidget (handle);
|
|
4185 if (widget is null) return 0;
|
|
4186 return widget.windowProc (handle, user_data);
|
|
4187 }
|
|
4188
|
|
4189 private static extern(C) int /*long*/ windowProcFunc3 (int /*long*/ handle, int /*long*/ arg0, int /*long*/ user_data) {
|
|
4190 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
4191 CallbackData* cbdata = cast(CallbackData*)user_data;
|
|
4192 return cbdata.display.windowProc( cast(GtkWidget*)handle, arg0, cast(int)cbdata.data );
|
|
4193 }
|
|
4194 int /*long*/ windowProc (GtkWidget* handle, int /*long*/ arg0, int /*long*/ user_data) {
|
|
4195 Widget widget = getWidget (handle);
|
|
4196 if (widget is null) return 0;
|
|
4197 return widget.windowProc (handle, arg0, user_data);
|
|
4198 }
|
|
4199
|
|
4200 private static extern(C) int /*long*/ windowProcFunc4 (int /*long*/ handle, int /*long*/ arg0, int /*long*/ arg1, int /*long*/ user_data) {
|
|
4201 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
4202 CallbackData* cbdata = cast(CallbackData*)user_data;
|
|
4203 return cbdata.display.windowProc( cast(GtkWidget*)handle, arg0, arg1, cast(int)cbdata.data );
|
|
4204 }
|
|
4205 int /*long*/ windowProc (GtkWidget* handle, int /*long*/ arg0, int /*long*/ arg1, int /*long*/ user_data) {
|
|
4206 Widget widget = getWidget (handle);
|
|
4207 if (widget is null) return 0;
|
|
4208 return widget.windowProc (handle, arg0, arg1, user_data);
|
|
4209 }
|
|
4210
|
|
4211 private static extern(C) int /*long*/ windowProcFunc5 (int /*long*/ handle, int /*long*/ arg0, int /*long*/ arg1, int /*long*/ arg2, int /*long*/ user_data) {
|
|
4212 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
4213 CallbackData* cbdata = cast(CallbackData*)user_data;
|
|
4214 return cbdata.display.windowProc( cast(GtkWidget*)handle, arg0, arg1, arg2, cast(int)cbdata.data );
|
|
4215 }
|
|
4216 int /*long*/ windowProc (GtkWidget* handle, int /*long*/ arg0, int /*long*/ arg1, int /*long*/ arg2, int /*long*/ user_data) {
|
|
4217 Widget widget = getWidget (handle);
|
|
4218 if (widget is null) return 0;
|
|
4219 return widget.windowProc (handle, arg0, arg1, arg2, user_data);
|
|
4220 }
|
|
4221
|
|
4222 package int doWindowTimerAdd( CallbackData* cbdata, int delay, GtkWidget* widget ){
|
|
4223 OS.g_object_set_data(cast(GObject*)widget, Display.classinfo.name.ptr, cast(void*)this);
|
|
4224 return OS.gtk_timeout_add (delay, &windowTimerProcFunc, widget);
|
|
4225 }
|
|
4226 private static extern(C) int /*long*/ windowTimerProcFunc (void* user_data) {
|
|
4227 version(LOG) getDwtLogger().error( __FILE__, __LINE__, "Display {}:", __LINE__ ).flush;
|
|
4228 Display d = cast(Display) OS.g_object_get_data(cast(GObject*)user_data, Display.classinfo.name.ptr );
|
|
4229 return d.windowTimerProc( cast(GtkWidget*)user_data );
|
|
4230 }
|
|
4231
|
|
4232 int /*long*/ windowTimerProc (GtkWidget* handle) {
|
|
4233 Widget widget = getWidget (handle);
|
|
4234 if (widget is null) return 0;
|
|
4235 return widget.timerProc (handle);
|
|
4236 }
|
|
4237
|
|
4238 }
|
|
4239
|
|
4240 package struct CallbackData {
|
|
4241 Display display;
|
|
4242 void* data;
|
|
4243 }
|
|
4244
|