root/dwt/widgets/Display.d

Revision 154:535243e6d16a, 170.5 kB (checked in by Jacob Carlborg <doob@me.com>, 3 years ago)

Fixes to make dwt compile with ldc

Line 
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  *     
11  * Port to the D programming language:
12  *     Jacob Carlborg <doob@me.com>
13  *******************************************************************************/
14 module dwt.widgets.Display;
15
16 import dwt.DWT;
17 import dwt.DWTError;
18 import dwt.DWTException;
19 import dwt.graphics.Color;
20 import dwt.graphics.Cursor;
21 import dwt.graphics.Device;
22 import dwt.graphics.DeviceData;
23 import dwt.graphics.GCData;
24 import dwt.graphics.Image;
25 import dwt.graphics.Point;
26 import dwt.graphics.Rectangle;
27 import dwt.internal.C;
28 import dwt.internal.cocoa.CGPoint;
29 import dwt.internal.cocoa.NSApplication;
30 import dwt.internal.cocoa.NSArray;
31 import dwt.internal.cocoa.NSAutoreleasePool;
32 import dwt.internal.cocoa.NSBundle;
33 import dwt.internal.cocoa.NSButton;
34 import dwt.internal.cocoa.NSColor;
35 import dwt.internal.cocoa.NSColorSpace;
36 import dwt.internal.cocoa.NSComboBox;
37 import dwt.internal.cocoa.NSDate;
38 import dwt.internal.cocoa.NSDictionary;
39 import dwt.internal.cocoa.NSEvent;
40 import dwt.internal.cocoa.NSGraphicsContext;
41 import dwt.internal.cocoa.NSImage;
42 import dwt.internal.cocoa.NSImageView;
43 import dwt.internal.cocoa.NSMenu;
44 import dwt.internal.cocoa.NSMenuItem;
45 import dwt.internal.cocoa.NSMutableDictionary;
46 import dwt.internal.cocoa.NSNumber;
47 import dwt.internal.cocoa.NSObject;
48 import dwt.internal.cocoa.NSPoint;
49 import dwt.internal.cocoa.NSPopUpButton;
50 import dwt.internal.cocoa.NSRange;
51 import dwt.internal.cocoa.NSRect;
52 import dwt.internal.cocoa.NSResponder;
53 import dwt.internal.cocoa.NSRunLoop;
54 import dwt.internal.cocoa.NSScreen;
55 import dwt.internal.cocoa.NSSearchField;
56 import dwt.internal.cocoa.NSSize;
57 import dwt.internal.cocoa.NSSlider;
58 import dwt.internal.cocoa.NSStepper;
59 import dwt.internal.cocoa.NSString;
60 import dwt.internal.cocoa.NSTextField;
61 import dwt.internal.cocoa.NSTextView;
62 import dwt.internal.cocoa.NSThread;
63 import dwt.internal.cocoa.NSTimer;
64 import dwt.internal.cocoa.NSView;
65 import dwt.internal.cocoa.NSWindow;
66 import dwt.internal.cocoa.NSWorkspace;
67 import dwt.internal.cocoa.OS;
68 import dwt.internal.cocoa.SWTApplicationDelegate;
69 import dwt.internal.cocoa.SWTWindowDelegate;
70 import cocoa = dwt.internal.cocoa.id;
71 import dwt.internal.cocoa.objc_super;
72
73 import tango.core.Thread;
74 import tango.stdc.stringz;
75
76 import dwt.dwthelper.System;
77 import dwt.dwthelper.utils;
78 import Carbon = dwt.internal.c.Carbon;
79 import dwt.internal.objc.cocoa.Cocoa;
80 import objc = dwt.internal.objc.runtime;
81 import dwt.widgets.Caret;
82 import dwt.widgets.ColorDialog;
83 import dwt.widgets.Control;
84 import dwt.widgets.Decorations;
85 import dwt.widgets.Dialog;
86 import dwt.widgets.Event;
87 import dwt.widgets.EventTable;
88 import dwt.widgets.FontDialog;
89 import dwt.widgets.Listener;
90 import dwt.widgets.Menu;
91 import dwt.widgets.MenuItem;
92 import dwt.widgets.Monitor;
93 import dwt.widgets.Shell;
94 import dwt.widgets.Synchronizer;
95 import dwt.widgets.Tray;
96 import dwt.widgets.Widget;
97
98 /**
99  * Instances of this class are responsible for managing the
100  * connection between DWT and the underlying operating
101  * system. Their most important function is to implement
102  * the DWT event loop in terms of the platform event model.
103  * They also provide various methods for accessing information
104  * about the operating system, and have overall control over
105  * the operating system resources which DWT allocates.
106  * <p>
107  * Applications which are built with DWT will <em>almost always</em>
108  * require only a single display. In particular, some platforms
109  * which DWT supports will not allow more than one <em>active</em>
110  * display. In other words, some platforms do not support
111  * creating a new display if one already exists that has not been
112  * sent the <code>dispose()</code> message.
113  * <p>
114  * In DWT, the thread which creates a <code>Display</code>
115  * instance is distinguished as the <em>user-interface thread</em>
116  * for that display.
117  * </p>
118  * The user-interface thread for a particular display has the
119  * following special attributes:
120  * <ul>
121  * <li>
122  * The event loop for that display must be run from the thread.
123  * </li>
124  * <li>
125  * Some DWT API methods (notably, most of the public methods in
126  * <code>Widget</code> and its subclasses), may only be called
127  * from the thread. (To support multi-threaded user-interface
128  * applications, class <code>Display</code> provides inter-thread
129  * communication methods which allow threads other than the
130  * user-interface thread to request that it perform operations
131  * on their behalf.)
132  * </li>
133  * <li>
134  * The thread is not allowed to construct other
135  * <code>Display</code>s until that display has been disposed.
136  * (Note that, this is in addition to the restriction mentioned
137  * above concerning platform support for multiple displays. Thus,
138  * the only way to have multiple simultaneously active displays,
139  * even on platforms which support it, is to have multiple threads.)
140  * </li>
141  * </ul>
142  * Enforcing these attributes allows DWT to be implemented directly
143  * on the underlying operating system's event model. This has
144  * numerous benefits including smaller footprint, better use of
145  * resources, safer memory management, clearer program logic,
146  * better performance, and fewer overall operating system threads
147  * required. The down side however, is that care must be taken
148  * (only) when constructing multi-threaded applications to use the
149  * inter-thread communication mechanisms which this class provides
150  * when required.
151  * </p><p>
152  * All DWT API methods which may only be called from the user-interface
153  * thread are distinguished in their documentation by indicating that
154  * they throw the "<code>ERROR_THREAD_INVALID_ACCESS</code>"
155  * DWT exception.
156  * </p>
157  * <dl>
158  * <dt><b>Styles:</b></dt>
159  * <dd>(none)</dd>
160  * <dt><b>Events:</b></dt>
161  * <dd>Close, Dispose, Settings</dd>
162  * </dl>
163  * <p>
164  * IMPORTANT: This class is <em>not</em> intended to be subclassed.
165  * </p>
166  * @see #syncExec
167  * @see #asyncExec
168  * @see #wake
169  * @see #readAndDispatch
170  * @see #sleep
171  * @see Device#dispose
172  * @see <a href="http://www.eclipse.org/swt/snippets/#display">Display snippets</a>
173  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
174  */
175 public class Display : Device {
176    
177     /* Windows and Events */
178     Event [] eventQueue;
179     EventTable eventTable, filterTable;
180     bool disposing;
181    
182     /* Sync/Async Widget Communication */
183     Synchronizer synchronizer;
184     Thread thread;
185     bool allowTimers, runAsyncMessages_;
186    
187     NSGraphicsContext[] contexts;
188    
189     Caret currentCaret;
190    
191     bool dragging;
192     Control currentControl, grabControl, trackingControl;
193    
194     NSDictionary markedAttributes;
195    
196     Shell [] modalShells;
197    
198     Menu menuBar;
199     Menu[] menus, popups;
200    
201     NSApplication application;
202     objc.Class applicationClass;
203     NSImage dockImage;
204     bool isEmbedded;
205    
206     Control focusControl;
207    
208     NSWindow screenWindow;
209     NSAutoreleasePool pool;
210     int loopCounter = 0;
211     bool idle;
212     static const short SWT_IDLE_TYPE = 1;
213    
214     int[] screenID;
215     NSPoint*[] screenCascade;
216    
217     /* Menus */
218     //  Menu menuBar;
219     //  static final int ID_TEMPORARY = 1000;
220     //  static final int ID_START = 1001;
221    
222     /* Display Shutdown */
223     Runnable [] disposeList;
224    
225     /* System Tray */
226     Tray tray;
227    
228     /* System Resources */
229     Image errorImage, infoImage, warningImage;
230     Cursor [] cursors;
231    
232     /* Key Mappings. */
233     static int [] [] KeyTable = [
234                                  
235                                  /* Keyboard and Mouse Masks */
236                                  [58,    DWT.ALT],
237                                  [56,    DWT.SHIFT],
238                                  [59,    DWT.CONTROL],
239                                  [55,    DWT.COMMAND],       
240                                  [61,    DWT.ALT],
241                                  [62,    DWT.CONTROL],
242                                  [60,    DWT.SHIFT],
243                                  [54,    DWT.COMMAND],
244                                  
245                                  /* Non-Numeric Keypad Keys */
246                                  [126, DWT.ARROW_UP],
247                                  [125, DWT.ARROW_DOWN],
248                                  [123, DWT.ARROW_LEFT],
249                                  [124, DWT.ARROW_RIGHT],
250                                  [116, DWT.PAGE_UP],
251                                  [121, DWT.PAGE_DOWN],
252                                  [115, DWT.HOME],
253                                  [119, DWT.END],
254                                  //   [??,    DWT.INSERT],
255                                  
256                                  /* Virtual and Ascii Keys */
257                                  [51,    DWT.BS],
258                                  [36,    DWT.CR],
259                                  [117,   DWT.DEL],
260                                  [53,    DWT.ESC],
261                                  [76,    DWT.LF],
262                                  [48,    DWT.TAB],   
263                                  
264                                  /* Functions Keys */
265                                  [122, DWT.F1],
266                                  [120, DWT.F2],
267                                  [99,    DWT.F3],
268                                  [118, DWT.F4],
269                                  [96,    DWT.F5],
270                                  [97,    DWT.F6],
271                                  [98,    DWT.F7],
272                                  [100, DWT.F8],
273                                  [101, DWT.F9],
274                                  [109, DWT.F10],
275                                  [103, DWT.F11],
276                                  [111, DWT.F12],
277                                  [105, DWT.F13],
278                                  [107, DWT.F14],
279                                  [113, DWT.F15],
280                                  
281                                  /* Numeric Keypad Keys */
282                                  [67, DWT.KEYPAD_MULTIPLY],
283                                  [69, DWT.KEYPAD_ADD],
284                                  [76, DWT.KEYPAD_CR],
285                                  [78, DWT.KEYPAD_SUBTRACT],
286                                  [65, DWT.KEYPAD_DECIMAL],
287                                  [75, DWT.KEYPAD_DIVIDE],
288                                  [82, DWT.KEYPAD_0],
289                                  [83, DWT.KEYPAD_1],
290                                  [84, DWT.KEYPAD_2],
291                                  [85, DWT.KEYPAD_3],
292                                  [86, DWT.KEYPAD_4],
293                                  [87, DWT.KEYPAD_5],
294                                  [88, DWT.KEYPAD_6],
295                                  [89, DWT.KEYPAD_7],
296                                  [91, DWT.KEYPAD_8],
297                                  [92, DWT.KEYPAD_9],
298                                  [81, DWT.KEYPAD_EQUAL],
299                                  
300                                  /* Other keys */
301                                  [57,    DWT.CAPS_LOCK],
302                                  [71,    DWT.NUM_LOCK],
303                                  //       [??,    DWT.SCROLL_LOCK],
304                                  //       [??,    DWT.PAUSE],
305                                  //       [??,    DWT.BREAK],
306                                  //       [??,    DWT.PRINT_SCREEN],
307                                  [114, DWT.HELP],
308                                  
309                                  ];
310    
311     static String APP_NAME = "DWT";
312     static const String ADD_WIDGET_KEY = "dwt.internal.addWidget";
313     static const String SWT_OBJECT = "SWT_OBJECT"; //$NON-NLS-1$
314    
315     /* Multiple Displays. */
316     static Display Default;
317     static Display [] Displays;
318    
319     /* Package Name */
320     static const String PACKAGE_PREFIX = "dwt.widgets.";
321    
322     /* Timer */
323     Runnable timerList [];
324     NSTimer nsTimers [];
325     SWTWindowDelegate timerDelegate;
326     SWTApplicationDelegate applicationDelegate;
327    
328     /* Display Data */
329     Object data;
330     String [] keys;
331     Object [] values;
332
333     /*
334      * TEMPORARY CODE.  Install the runnable that
335      * gets the current display. This code will
336      * be removed in the future.
337      */
338     static this () {
339         Displays = new Display [4];
340         DeviceFinder = new class Runnable {
341             public void run () {
342                 Device device = getCurrent ();
343                 if (device is null) {
344                     device = getDefault ();
345                 }
346                 setDevice (device);
347             }
348         };
349     }
350    
351     /*
352      * TEMPORARY CODE.
353      */
354     static void setDevice (Device device) {
355         CurrentDevice = device;
356     }
357    
358     static char* ascii (String name) {
359         /*int length = name.length ();
360          char [] chars = new char [length];
361          name.getChars (0, length, chars, 0);
362          byte [] buffer = new byte [length + 1];
363          for (int i=0; i<length; i++) {
364          buffer [i] = cast(byte) chars [i];
365          }
366          return buffer;*/
367         return name.toStringz();
368     }
369    
370     static int translateKey (int key) {
371         for (int i=0; i<KeyTable.length; i++) {
372             if (KeyTable [i] [0] is key) return KeyTable [i] [1];
373         }
374         return 0;
375     }
376    
377     static int untranslateKey (int key) {
378         for (int i=0; i<KeyTable.length; i++) {
379             if (KeyTable [i] [1] is key) return KeyTable [i] [0];
380         }
381         return 0;
382     }
383    
384     void addContext (NSGraphicsContext context) {
385         if (contexts is null) contexts = new NSGraphicsContext [12];
386         for (int i=0; i<contexts.length; i++) {
387             if (contexts[i] !is null && contexts [i].id is context.id) {
388                 contexts [i] = context;
389                 return;
390             }
391         }
392         NSGraphicsContext [] newContexts = new NSGraphicsContext [contexts.length + 12];
393         newContexts [contexts.length] = context;
394         System.arraycopy (contexts, 0, newContexts, 0, contexts.length);
395         contexts = newContexts;
396     }
397    
398     /**
399      * Adds the listener to the collection of listeners who will
400      * be notified when an event of the given type occurs anywhere
401      * in a widget. The event type is one of the event constants
402      * defined in class <code>DWT</code>. When the event does occur,
403      * the listener is notified by sending it the <code>handleEvent()</code>
404      * message.
405      * <p>
406      * Setting the type of an event to <code>DWT.None</code> from
407      * within the <code>handleEvent()</code> method can be used to
408      * change the event type and stop subsequent Java listeners
409      * from running. Because event filters run before other listeners,
410      * event filters can both block other listeners and set arbitrary
411      * fields within an event. For this reason, event filters are both
412      * powerful and dangerous. They should generally be avoided for
413      * performance, debugging and code maintenance reasons.
414      * </p>
415      *
416      * @param eventType the type of event to listen for
417      * @param listener the listener which should be notified when the event occurs
418      *
419      * @exception IllegalArgumentException <ul>
420      *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
421      * </ul>
422      * @exception DWTException <ul>
423      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
424      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
425      * </ul>
426      *
427      * @see Listener
428      * @see DWT
429      * @see #removeFilter
430      * @see #removeListener
431      *
432      * @since 3.0
433      */
434     public void addFilter (int eventType, Listener listener) {
435         checkDevice ();
436         if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
437         if (filterTable is null) filterTable = new EventTable ();
438         filterTable.hook (eventType, listener);
439     }
440    
441     /**
442      * Adds the listener to the collection of listeners who will
443      * be notified when an event of the given type occurs. The event
444      * type is one of the event constants defined in class <code>DWT</code>.
445      * When the event does occur in the display, the listener is notified by
446      * sending it the <code>handleEvent()</code> message.
447      *
448      * @param eventType the type of event to listen for
449      * @param listener the listener which should be notified when the event occurs
450      *
451      * @exception IllegalArgumentException <ul>
452      *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
453      * </ul>
454      * @exception DWTException <ul>
455      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
456      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
457      * </ul>
458      *
459      * @see Listener
460      * @see DWT
461      * @see #removeListener
462      *
463      * @since 2.0
464      */
465     public void addListener (int eventType, Listener listener) {
466         checkDevice ();
467         if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
468         if (eventTable is null) eventTable = new EventTable ();
469         eventTable.hook (eventType, listener);
470     }
471    
472     void addMenu (Menu menu) {
473         if (menus is null) menus = new Menu [12];
474         for (int i=0; i<menus.length; i++) {
475             if (menus [i] is null) {
476                 menus [i] = menu;
477                 return;
478             }
479         }
480         Menu [] newMenus = new Menu [menus.length + 12];
481         newMenus [menus.length] = menu;
482         System.arraycopy (menus, 0, newMenus, 0, menus.length);
483         menus = newMenus;
484     }
485    
486     void addPopup (Menu menu) {
487         if (popups is null) popups = new Menu [4];
488         size_t length_ = popups.length;
489         for (size_t i=0; i<length_; i++) {
490             if (popups [i] is menu) return;
491         }
492         size_t index = 0;
493         while (index < length_) {
494             if (popups [index] is null) break;
495             index++;
496         }
497         if (index is length_) {
498             Menu [] newPopups = new Menu [length_ + 4];
499             System.arraycopy (popups, 0, newPopups, 0, length_);
500             popups = newPopups;
501         }
502         popups [index] = menu;
503     }
504    
505     void addWidget (NSObject view, Widget widget) {
506         if (view is null) return;
507         OS.object_setInstanceVariable (view.id, SWT_OBJECT, widget.jniRef);
508     }
509    
510     /**
511      * Causes the <code>run()</code> method of the runnable to
512      * be invoked by the user-interface thread at the next
513      * reasonable opportunity. The caller of this method continues
514      * to run in parallel, and is not notified when the
515      * runnable has completed.  Specifying <code>null</code> as the
516      * runnable simply wakes the user-interface thread when run.
517      * <p>
518      * Note that at the time the runnable is invoked, widgets
519      * that have the receiver as their display may have been
520      * disposed. Therefore, it is necessary to check for this
521      * case inside the runnable before accessing the widget.
522      * </p>
523      *
524      * @param runnable code to run on the user-interface thread or <code>null</code>
525      *
526      * @exception DWTException <ul>
527      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
528      * </ul>
529      *
530      * @see #syncExec
531      */
532     public void asyncExec (Runnable runnable) {
533         synchronized (Device.classinfo) {
534             if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
535             synchronizer.asyncExec (runnable);
536         }
537     }
538    
539     /**
540      * Causes the system hardware to emit a short sound
541      * (if it supports this capability).
542      *
543      * @exception DWTException <ul>
544      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
545      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
546      * </ul>
547      */
548     public void beep () {
549         checkDevice ();
550         OS.NSBeep ();
551     }
552    
553     void cascadeWindow (NSWindow window, NSScreen screen) {
554         NSDictionary dictionary = screen.deviceDescription();
555         int screenNumber = (new NSNumber(dictionary.objectForKey(NSString.stringWith("NSScreenNumber")).id)).intValue();
556         int index = 0;
557         while (screenID[index] !is 0 && screenID[index] !is screenNumber) index++;
558         screenID[index] = screenNumber;
559         NSPoint* cascade = screenCascade[index];
560         if (cascade is null) {
561             NSRect frame = screen.frame();
562             NSPoint nsPoint;
563             cascade = &nsPoint;
564             cascade.x = frame.x;
565             cascade.y = frame.y + frame.height;
566          }
567         screenCascade[index] = &window.cascadeTopLeftFromPoint(*cascade);
568     }
569    
570     protected void checkDevice () {
571         if (thread is null) error (DWT.ERROR_WIDGET_DISPOSED);
572         if (thread !is Thread.getThis ()) error (DWT.ERROR_THREAD_INVALID_ACCESS);
573         if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
574     }
575    
576     /**
577      * Checks that this class can be subclassed.
578      * <p>
579      * IMPORTANT: See the comment in <code>Widget.checkSubclass()</code>.
580      * </p>
581      *
582      * @exception DWTException <ul>
583      *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
584      * </ul>
585      *
586      * @see Widget#checkSubclass
587      */
588     protected void checkSubclass () {
589         if (!Display.isValidClass (this.classinfo)) error (DWT.ERROR_INVALID_SUBCLASS);
590     }
591    
592     /**
593      * Constructs a new instance of this class.
594      * <p>
595      * Note: The resulting display is marked as the <em>current</em>
596      * display. If this is the first display which has been
597      * constructed since the application started, it is also
598      * marked as the <em>default</em> display.
599      * </p>
600      *
601      * @exception DWTException <ul>
602      *    <li>ERROR_THREAD_INVALID_ACCESS - if called from a thread that already created an existing display</li>
603      *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
604      * </ul>
605      *
606      * @see #getCurrent
607      * @see #getDefault
608      * @see Widget#checkSubclass
609      * @see Shell
610      */
611     public this () {
612         this (null);
613     }
614    
615     /**
616      * Constructs a new instance of this class using the parameter.
617      *
618      * @param data the device data
619      */
620     public this (DeviceData data) {
621         super (data);
622         screenID = new int[32];
623         screenCascade = new NSPoint*[32];
624         cursors = new Cursor [DWT.CURSOR_HAND + 1];
625         timerDelegate = cast(SWTWindowDelegate)(new SWTWindowDelegate()).alloc().init();
626        
627         caretTimer = new CaretTimer;
628         hoverTimer = new HoverTimer;
629     }
630    
631     static void checkDisplay (Thread thread, bool multiple) {
632         synchronized (Device.classinfo) {
633             for (int i=0; i<Displays.length; i++) {
634                 if (Displays [i] !is null) {
635                     if (!multiple) DWT.error (DWT.ERROR_NOT_IMPLEMENTED, null, " [multiple displays]");
636                     if (Displays [i].thread is thread) DWT.error (DWT.ERROR_THREAD_INVALID_ACCESS);
637                 }
638             }
639         }
640     }
641    
642     static String convertToLf(String text) {
643         char Cr = '\r';
644         char Lf = '\n';
645         int length = text.length ();
646         if (length is 0) return text;
647        
648         /* Check for an LF or CR/LF.  Assume the rest of the string
649          * is formated that way.  This will not work if the string
650          * contains mixed delimiters. */
651         int i = text.indexOf (Lf, 0);
652         if (i is -1 || i is 0) return text;
653         if (text.charAt (i - 1) !is Cr) return text;
654        
655         /* The string is formatted with CR/LF.
656          * Create a new string with the LF line delimiter. */
657         i = 0;
658         StringBuffer result = new StringBuffer ();
659         while (i < length) {
660             int j = text.indexOf (Cr, i);
661             if (j is -1) j = length;
662             String s = text.substring (i, j);
663             result.append (s);
664             i = j + 2;
665             result.append (Lf);
666         }
667         return result.toString ();
668     }
669    
670     void clearModal (Shell shell) {
671         if (modalShells is null) return;
672         int index = 0, length_ = modalShells.length;
673         while (index < length_) {
674             if (modalShells [index] is shell) break;
675             if (modalShells [index] is null) return;
676             index++;
677         }
678         if (index is length_) return;
679         System.arraycopy (modalShells, index + 1, modalShells, index, --length_ - index);
680         modalShells [length_] = null;
681         if (index is 0 && modalShells [0] is null) modalShells = null;
682         Shell [] shells = getShells ();
683         for (int i=0; i<shells.length; i++) shells [i].updateModal ();
684     }
685    
686     /**
687      * Requests that the connection between DWT and the underlying
688      * operating system be closed.
689      *
690      * @exception DWTException <ul>
691      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
692      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
693      * </ul>
694      *
695      * @see Device#dispose
696      *
697      * @since 2.0
698      */
699     public void close () {
700         checkDevice ();
701         Event event = new Event ();
702         sendEvent (DWT.Close, event);
703         if (event.doit) dispose ();
704     }
705    
706     /**
707      * Creates the device in the operating system.  If the device
708      * does not have a handle, this method may do nothing depending
709      * on the device.
710      * <p>
711      * This method is called before <code>init</code>.
712      * </p>
713      *
714      * @param data the DeviceData which describes the receiver
715      *
716      * @see #init
717      */
718     protected void create (DeviceData data) {
719         checkSubclass ();
720         checkDisplay (thread = Thread.getThis (), false);
721         createDisplay (data);
722         register (this);
723         synchronizer = new Synchronizer (this);
724         if (Default is null) Default = this;
725     }
726    
727     void createDisplay (DeviceData data) {
728         if (OS.VERSION < 0x1050) {
729             System.out_.println ("***WARNING: DWT requires MacOS X version {}{}{}{}" , 10 , "." , 5 , " or greater"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
730             System.out_.println ("***WARNING: Detected: {}{}{}{}{}" , Integer.toHexString((OS.VERSION & 0xFF00) >> 8) , "." , Integer.toHexString((OS.VERSION & 0xF0) >> 4) , "." , Integer.toHexString(OS.VERSION & 0xF)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
731             error(DWT.ERROR_NOT_IMPLEMENTED);
732         }
733        
734         NSThread nsthread = NSThread.currentThread();
735         NSMutableDictionary dictionary = nsthread.threadDictionary();
736         NSString key = NSString.stringWith("SWT_NSAutoreleasePool");
737         pool = new NSAutoreleasePool(dictionary.objectForKey(key));
738        
739         application = NSApplication.sharedApplication();
740        
741         /*
742          * TODO: If an NSApplication is already running we don't want to create another NSApplication.
743          * But if we don't we won't get mouse events, since we currently need to subclass NSApplication and intercept sendEvent to
744          * deliver mouse events correctly to widgets.   
745          */
746         if (!application.isRunning()) {
747             /*
748              * Feature in the Macintosh.  On OS 10.2, it is necessary
749              * to explicitly check in with the Process Manager and set
750              * the current process to be the front process in order for
751              * windows to come to the front by default.  The fix is call
752              * both GetCurrentProcess() and SetFrontProcess().
753              *
754              * NOTE: It is not actually necessary to use the process
755              * serial number returned by GetCurrentProcess() in the
756              * call to SetFrontProcess() (ie. kCurrentProcess can be
757              * used) but both functions must be called in order for
758              * windows to come to the front.
759              */
760             Carbon.ProcessSerialNumber psn;
761             if (OS.GetCurrentProcess (&psn) is OS.noErr) {
762                 int pid = OS.getpid ();
763                 char* ptr = OS.getenv (ascii ("APP_NAME_" ~ Integer.toString(pid)));
764                 if (ptr is null && APP_NAME !is null) {
765                     ptr = NSString.stringWith(APP_NAME).UTF8String();   
766                 }
767                 if (ptr !is null) OS.CPSSetProcessName (&psn, ptr);
768                 OS.TransformProcessType (&psn, OS.kProcessTransformToForegroundApplication);
769                 OS.SetFrontProcess (&psn);
770                 ptr = OS.getenv (ascii ("APP_ICON_" ~ Integer.toString(pid)));
771                 if (ptr !is null) {
772                     NSString path = NSString.stringWithUTF8String (ptr);
773                     NSImage image = cast(NSImage) (new NSImage()).alloc();
774                     image = image.initByReferencingFile(path);
775                     dockImage = image;
776                     application.setApplicationIconImage(image);
777                 }
778             }
779            
780             String className = "SWTApplication";
781             objc.Class cls;
782             if ((cls = cast(objc.Class) OS.objc_lookUpClass (className)) is null) {
783                 objc.IMP proc2 = cast(objc.IMP) &applicationProc2;
784                 objc.IMP proc3 = cast(objc.IMP) &applicationProc3;
785                 objc.IMP proc6 = cast(objc.IMP) &applicationProc6;
786                 cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSApplication, className, 0);
787                 OS.class_addMethod(cls, OS.sel_registerName("sendEvent:"), proc3, "@:@");
788                
789                 static if ((void*).sizeof > int.sizeof) // 64bit target
790                     OS.class_addMethod(cls, OS.sel_nextEventMatchingMask_untilDate_inMode_dequeue_, proc6, "@:Q@@B");
791                 else
792                     OS.class_addMethod(cls, OS.sel_nextEventMatchingMask_untilDate_inMode_dequeue_, proc6, "@:I@@B");
793                
794                 OS.class_addMethod(cls, OS.sel_isRunning, proc2, "@:");
795                 OS.objc_registerClassPair(cls);
796             }       
797             applicationClass = OS.object_setClass(application.id, cls);
798         } else {
799             isEmbedded = true;
800         }
801        
802         //  application = new NSApplication(OS.objc_msgSend(cls, OS.sel_sharedApplication));
803     }
804    
805     static void deregister (Display display) {
806         synchronized (Device.classinfo) {
807             for (int i=0; i<Displays.length; i++) {
808                 if (display is Displays [i]) Displays [i] = null;
809             }
810         }
811     }
812    
813     /**
814      * Destroys the device in the operating system and releases
815      * the device's handle.  If the device does not have a handle,
816      * this method may do nothing depending on the device.
817      * <p>
818      * This method is called after <code>release</code>.
819      * </p>
820      * @see Device#dispose
821      * @see #release
822      */
823     protected void destroy () {
824         if (this is Default) Default = null;
825         deregister (this);
826         destroyDisplay ();
827     }
828    
829     void destroyDisplay () {
830         application = null;
831     }
832    
833     /**
834      * Causes the <code>run()</code> method of the runnable to
835      * be invoked by the user-interface thread just before the
836      * receiver is disposed.  Specifying a <code>null</code> runnable
837      * is ignored.
838      *
839      * @param runnable code to run at dispose time.
840      *
841      * @exception DWTException <ul>
842      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
843      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
844      * </ul>
845      */
846     public void disposeExec (Runnable runnable) {
847         checkDevice ();
848         if (disposeList is null) disposeList = new Runnable [4];
849         for (int i=0; i<disposeList.length; i++) {
850             if (disposeList [i] is null) {
851                 disposeList [i] = runnable;
852                 return;
853             }
854         }
855         Runnable [] newDisposeList = new Runnable [disposeList.length + 4];
856         SimpleType!(Runnable).arraycopy (disposeList, 0, newDisposeList, 0, disposeList.length);
857         newDisposeList [disposeList.length] = runnable;
858         disposeList = newDisposeList;
859     }
860    
861     void error (int code) {
862         DWT.error(code);
863     }
864    
865     bool filterEvent (Event event) {
866         if (filterTable !is null) filterTable.sendEvent (event);
867         return false;
868     }
869    
870     bool filters (int eventType) {
871         if (filterTable is null) return false;
872         return filterTable.hooks (eventType);
873     }
874    
875     /**
876      * Given the operating system handle for a widget, returns
877      * the instance of the <code>Widget</code> subclass which
878      * represents it in the currently running application, if
879      * such exists, or null if no matching widget can be found.
880      * <p>
881      * <b>IMPORTANT:</b> This method should not be called from
882      * application code. The arguments are platform-specific.
883      * </p>
884      *
885      * @param handle the handle for the widget
886      * @return the DWT widget that the handle represents
887      *
888      * @exception DWTException <ul>
889      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
890      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
891      * </ul>
892      */
893     public Widget findWidget (objc.id handle) {
894         checkDevice ();
895         return getWidget (handle);
896     }
897    
898     /**
899      * Given the operating system handle for a widget,
900      * and widget-specific id, returns the instance of
901      * the <code>Widget</code> subclass which represents
902      * the handle/id pair in the currently running application,
903      * if such exists, or null if no matching widget can be found.
904      * <p>
905      * <b>IMPORTANT:</b> This method should not be called from
906      * application code. The arguments are platform-specific.
907      * </p>
908      *
909      * @param handle the handle for the widget
910      * @param id the id for the subwidget (usually an item)
911      * @return the DWT widget that the handle/id pair represents
912      *
913      * @exception DWTException <ul>
914      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
915      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
916      * </ul>
917      *
918      * @since 3.1
919      */
920     public Widget findWidget (objc.id handle, int id) {
921         checkDevice ();
922         return getWidget (handle);
923     }
924    
925     /**
926      * Given a widget and a widget-specific id, returns the
927      * instance of the <code>Widget</code> subclass which represents
928      * the widget/id pair in the currently running application,
929      * if such exists, or null if no matching widget can be found.
930      *
931      * @param widget the widget
932      * @param id the id for the subwidget (usually an item)
933      * @return the DWT subwidget (usually an item) that the widget/id pair represents
934      *
935      * @exception DWTException <ul>
936      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
937      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
938      * </ul>
939      *
940      * @since 3.3
941      */
942     public Widget findWidget (Widget widget, int id) {
943         checkDevice ();
944         return null;
945     }
946    
947     /**
948      * Returns the display which the given thread is the
949      * user-interface thread for, or null if the given thread
950      * is not a user-interface thread for any display.  Specifying
951      * <code>null</code> as the thread will return <code>null</code>
952      * for the display.
953      *
954      * @param thread the user-interface thread
955      * @return the display for the given thread
956      */
957     public static Display findDisplay (Thread thread) {
958         synchronized (Device.classinfo) {
959             for (int i=0; i<Displays.length; i++) {
960                 Display display = Displays [i];
961                 if (display !is null && display.thread is thread) {
962                     return display;
963                 }
964             }
965             return null;
966         }
967     }
968    
969     /**
970      * Returns the currently active <code>Shell</code>, or null
971      * if no shell belonging to the currently running application
972      * is active.
973      *
974      * @return the active shell or null
975      *
976      * @exception DWTException <ul>
977      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
978      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
979      * </ul>
980      */
981     public Shell getActiveShell () {
982         checkDevice ();
983         NSArray windows = application.windows();
984         int count = cast(int)/*64*/windows.count();
985         for (int i = 0; i < count; i++) {
986             NSWindow win = new NSWindow(windows.objectAtIndex(i));
987             if (win.isKeyWindow()) {
988                 Widget widget = getWidget(win.contentView());
989                 if (cast(Shell) widget) {
990                     return cast(Shell)widget;
991                 }
992             }
993         }
994         return null;
995     }
996    
997     /**
998      * Returns a rectangle describing the receiver's size and location. Note that
999      * on multi-monitor systems the origin can be negative.
1000      *
1001      * @return the bounding rectangle
1002      *
1003      * @exception DWTException <ul>
1004      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1005      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1006      * </ul>
1007      */
1008     public Rectangle getBounds () {
1009         checkDevice ();
1010         NSArray screens = NSScreen.screens();
1011         return getBounds (screens);
1012     }
1013    
1014     Rectangle getBounds (NSArray screens) {
1015         NSRect primaryFrame = (new NSScreen(screens.objectAtIndex(0))).frame();
1016         CGFloat minX = CGFloat.max, maxX = CGFloat.min;
1017         CGFloat minY = CGFloat.max, maxY = CGFloat.min;
1018         NSUInteger count = screens.count();
1019         for (NSUInteger i = 0; i < count; i++) {
1020             NSScreen screen = new NSScreen(screens.objectAtIndex(i));
1021             NSRect frame = screen.frame();
1022             CGFloat x1 = frame.x, x2 = frame.x + frame.width;
1023             CGFloat y1 = primaryFrame.height - frame.y, y2 = primaryFrame.height - (frame.y + frame.height);
1024             if (x1 < minX) minX = x1;
1025             if (x2 < minX) minX = x2;
1026             if (x1 > maxX) maxX = x1;
1027             if (x2 > maxX) maxX = x2;
1028             if (y1 < minY) minY = y1;
1029             if (y2 < minY) minY = y2;
1030             if (y1 > maxY) maxY = y1;
1031             if (y2 > maxY) maxY = y2;
1032         }
1033         return new Rectangle (cast(int)minX, cast(int)minY, cast(int)(maxX - minX), cast(int)(maxY - minY));
1034     }
1035    
1036     /**
1037      * Returns the display which the currently running thread is
1038      * the user-interface thread for, or null if the currently
1039      * running thread is not a user-interface thread for any display.
1040      *
1041      * @return the current display
1042      */
1043     public static Display getCurrent () {
1044         return findDisplay (Thread.getThis ());
1045     }
1046    
1047     int getCaretBlinkTime () {
1048         checkDevice ();
1049         return 560;
1050     }
1051    
1052     /**
1053      * Returns a rectangle which describes the area of the
1054      * receiver which is capable of displaying data.
1055      *
1056      * @return the client area
1057      *
1058      * @exception DWTException <ul>
1059      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1060      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1061      * </ul>
1062      *
1063      * @see #getBounds
1064      */
1065     public Rectangle getClientArea () {
1066         checkDevice ();
1067         NSArray screens = NSScreen.screens();
1068         if (screens.count() !is 1) return getBounds (screens);
1069         NSScreen screen = new NSScreen(screens.objectAtIndex(0));
1070         NSRect frame = screen.frame();
1071         NSRect visibleFrame = screen.visibleFrame();
1072         CGFloat y = frame.height - (visibleFrame.y + visibleFrame.height);
1073         return new Rectangle(cast(int)visibleFrame.x, cast(int)y, cast(int)visibleFrame.width, cast(int)visibleFrame.height);
1074     }
1075    
1076     /**
1077      * Returns the control which the on-screen pointer is currently
1078      * over top of, or null if it is not currently over one of the
1079      * controls built by the currently running application.
1080      *
1081      * @return the control under the cursor
1082      *
1083      * @exception DWTException <ul>
1084      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1085      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1086      * </ul>
1087      */
1088     public Control getCursorControl () {
1089         checkDevice();
1090         return findControl(null, false, false, true);
1091     }
1092    
1093     /**
1094      * Returns the location of the on-screen pointer relative
1095      * to the top left corner of the screen.
1096      *
1097      * @return the cursor location
1098      *
1099      * @exception DWTException <ul>
1100      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1101      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1102      * </ul>
1103      */
1104     public Point getCursorLocation () {
1105         checkDevice ();
1106         NSPoint location = NSEvent.mouseLocation();
1107         NSRect primaryFrame = getPrimaryFrame();
1108         return new Point (cast(int) location.x, cast(int) (primaryFrame.height - location.y));
1109     }
1110    
1111     /**
1112      * Returns an array containing the recommended cursor sizes.
1113      *
1114      * @return the array of cursor sizes
1115      *
1116      * @exception DWTException <ul>
1117      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1118      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1119      * </ul>
1120      *
1121      * @since 3.0
1122      */
1123     public Point [] getCursorSizes () {
1124         checkDevice ();
1125         return [new Point (16, 16)];
1126     }
1127    
1128     /**
1129      * Returns the default display. One is created (making the
1130      * thread that invokes this method its user-interface thread)
1131      * if it did not already exist.
1132      *
1133      * @return the default display
1134      */
1135     public static Display getDefault () {
1136         synchronized (Device.classinfo) {
1137             if (Default is null) Default = new Display ();
1138             return Default;
1139         }
1140     }
1141    
1142     /**
1143      * Returns the application defined property of the receiver
1144      * with the specified name, or null if it has not been set.
1145      * <p>
1146      * Applications may have associated arbitrary objects with the
1147      * receiver in this fashion. If the objects stored in the
1148      * properties need to be notified when the display is disposed
1149      * of, it is the application's responsibility to provide a
1150      * <code>disposeExec()</code> handler which does so.
1151      * </p>
1152      *
1153      * @param key the name of the property
1154      * @return the value of the property or null if it has not been set
1155      *
1156      * @exception IllegalArgumentException <ul>
1157      *    <li>ERROR_NULL_ARGUMENT - if the key is null</li>
1158      * </ul>
1159      * @exception DWTException <ul>
1160      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1161      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1162      * </ul>
1163      *
1164      * @see #setData(String, Object)
1165      * @see #disposeExec(Runnable)
1166      */
1167     public Object getData (String key) {
1168         checkDevice ();
1169         //if (key is null) error (DWT.ERROR_NULL_ARGUMENT);
1170         if (keys is null) return null;
1171         for (int i=0; i<keys.length; i++) {
1172             if (keys [i].equals (key)) return values [i];
1173         }
1174         return null;
1175     }
1176    
1177     /**
1178      * Returns the application defined, display specific data
1179      * associated with the receiver, or null if it has not been
1180      * set. The <em>display specific data</em> is a single,
1181      * unnamed field that is stored with every display.
1182      * <p>
1183      * Applications may put arbitrary objects in this field. If
1184      * the object stored in the display specific data needs to
1185      * be notified when the display is disposed of, it is the
1186      * application's responsibility to provide a
1187      * <code>disposeExec()</code> handler which does so.
1188      * </p>
1189      *
1190      * @return the display specific data
1191      *
1192      * @exception DWTException <ul>
1193      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1194      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1195      * </ul>
1196      *
1197      * @see #setData(Object)
1198      * @see #disposeExec(Runnable)
1199      */
1200     public Object getData () {
1201         checkDevice ();
1202         return data;
1203     }
1204    
1205     /**
1206      * Returns the button dismissal align_ment, one of <code>LEFT</code> or <code>RIGHT</code>.
1207      * The button dismissal align_ment is the ordering that should be used when positioning the
1208      * default dismissal button for a dialog.  For example, in a dialog that contains an OK and
1209      * CANCEL button, on platforms where the button dismissal align_ment is <code>LEFT</code>, the
1210      * button ordering should be OK/CANCEL.  When button dismissal align_ment is <code>RIGHT</code>,
1211      * the button ordering should be CANCEL/OK.
1212      *
1213      * @return the button dismissal order
1214      *
1215      * @exception DWTException <ul>
1216      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1217      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1218      * </ul>
1219      *
1220      * @since 2.1
1221      */
1222     public int getDismissalAlignment () {
1223         checkDevice ();
1224         return DWT.RIGHT;
1225     }
1226    
1227     /**
1228      * Returns the longest duration, in milliseconds, between
1229      * two mouse button clicks that will be considered a
1230      * <em>double click</em> by the underlying operating system.
1231      *
1232      * @return the double click time
1233      *
1234      * @exception DWTException <ul>
1235      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1236      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1237      * </ul>
1238      */
1239     public int getDoubleClickTime () {
1240         checkDevice ();
1241         return 0;
1242         //  return OS.GetDblTime () * 1000 / 60;
1243     }
1244    
1245     /**
1246      * Returns the control which currently has keyboard focus,
1247      * or null if keyboard events are not currently going to
1248      * any of the controls built by the currently running
1249      * application.
1250      *
1251      * @return the control under the cursor
1252      *
1253      * @exception DWTException <ul>
1254      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1255      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1256      * </ul>
1257      */
1258     public Control getFocusControl () {
1259         checkDevice ();
1260         NSWindow window = application.keyWindow();
1261         return GetFocusControl(window);
1262     }
1263    
1264     static Control GetFocusControl(NSWindow window) {
1265         if (window !is null) {
1266             NSResponder responder = window.firstResponder();
1267             if (responder !is null && !responder.respondsToSelector(OS.sel_superview)) {
1268                 return null;
1269             }
1270             NSView view = new NSView(responder.id);
1271             if (view !is null) {
1272                 do {
1273                     Widget widget = GetWidget (view.id);
1274                     if (cast(Control)widget) {
1275                         return cast(Control)widget;
1276                     }
1277                     view = view.superview();
1278                 } while (view !is null);
1279             }
1280         }
1281         return null;
1282     }
1283    
1284     /**
1285      * Returns true when the high contrast mode is enabled.
1286      * Otherwise, false is returned.
1287      * <p>
1288      * Note: This operation is a hint and is not supported on
1289      * platforms that do not have this concept.
1290      * </p>
1291      *
1292      * @return the high contrast mode
1293      *
1294      * @exception DWTException <ul>
1295      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1296      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1297      * </ul>
1298      *
1299      * @since 3.0
1300      */
1301     public bool getHighContrast () {
1302         checkDevice ();
1303         return false;
1304     }
1305    
1306     /**
1307      * Returns the maximum allowed depth of icons on this display, in bits per pixel.
1308      * On some platforms, this may be different than the actual depth of the display.
1309      *
1310      * @return the maximum icon depth
1311      *
1312      * @exception DWTException <ul>
1313      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1314      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1315      * </ul>
1316      *
1317      * @see Device#getDepth
1318      */
1319     public int getIconDepth () {
1320         return getDepth ();
1321     }
1322    
1323     /**
1324      * Returns an array containing the recommended icon sizes.
1325      *
1326      * @return the array of icon sizes
1327      *
1328      * @exception DWTException <ul>
1329      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1330      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1331      * </ul>
1332      *
1333      * @see Decorations#setImages(Image[])
1334      *
1335      * @since 3.0
1336      */
1337     public Point [] getIconSizes () {
1338         checkDevice ();
1339         return [
1340                 new Point (16, 16), new Point (32, 32),
1341                 new Point (64, 64), new Point (128, 128)]; 
1342     }
1343    
1344     int getLastEventTime () {
1345         /*
1346          * This code is intentionally commented.  Event time is
1347          * in seconds and we need an accurate time in milliseconds.
1348          */
1349         //  return (int) (OS.GetLastUserEventTime () * 1000.0);
1350         return cast(int) System.currentTimeMillis ();
1351     }
1352    
1353     Menu [] getMenus (Decorations shell) {
1354         if (menus is null) return new Menu [0];
1355         int count = 0;
1356         for (int i = 0; i < menus.length; i++) {
1357             Menu menu = menus[i];
1358             if (menu !is null && menu.parent is shell) count++;
1359         }
1360         int index = 0;
1361         Menu[] result = new Menu[count];
1362         for (int i = 0; i < menus.length; i++) {
1363             Menu menu = menus[i];
1364             if (menu !is null && menu.parent is shell) {
1365                 result[index++] = menu;
1366             }
1367         }
1368         return result;
1369     }
1370    
1371     int getMessageCount () {
1372         return synchronizer.getMessageCount ();
1373     }
1374    
1375     /**
1376      * Returns an array of monitors attached to the device.
1377      *
1378      * @return the array of monitors
1379      *
1380      * @since 3.0
1381      */
1382     public dwt.widgets.Monitor.Monitor [] getMonitors () {
1383         checkDevice ();
1384         NSArray screens = NSScreen.screens();
1385         NSRect primaryFrame = (new NSScreen(screens.objectAtIndex(0))).frame();
1386         NSUInteger count = screens.count();
1387         dwt.widgets.Monitor.Monitor [] monitors = new dwt.widgets.Monitor.Monitor [count];
1388         for (NSUInteger i=0; i<count; i++) {
1389             dwt.widgets.Monitor.Monitor monitor = new dwt.widgets.Monitor.Monitor ();
1390             NSScreen screen = new NSScreen(screens.objectAtIndex(i));
1391             NSRect frame = screen.frame();
1392             monitor.x = cast(int)frame.x;
1393             monitor.y = cast(int)(primaryFrame.height - (frame.y + frame.height));
1394             monitor.width = cast(int)frame.width;
1395             monitor.height = cast(int)frame.height;
1396             NSRect visibleFrame = screen.visibleFrame();
1397             monitor.clientX = cast(int)visibleFrame.x;
1398             monitor.clientY = cast(int)(primaryFrame.height - (visibleFrame.y + visibleFrame.height));
1399             monitor.clientWidth = cast(int)visibleFrame.width;
1400             monitor.clientHeight = cast(int)visibleFrame.height;
1401             monitors [i] = monitor;
1402         }
1403         return monitors;
1404     }
1405    
1406     NSRect getPrimaryFrame () {
1407         NSArray screens = NSScreen.screens();
1408         return (new NSScreen(screens.objectAtIndex(0))).frame();
1409     }
1410    
1411     /**
1412      * Returns the primary monitor for that device.
1413      *
1414      * @return the primary monitor
1415      *
1416      * @since 3.0
1417      */
1418     public dwt.widgets.Monitor.Monitor getPrimaryMonitor () {
1419         checkDevice ();
1420         dwt.widgets.Monitor.Monitor monitor = new dwt.widgets.Monitor.Monitor ();
1421         NSArray screens = NSScreen.screens();
1422         NSScreen screen = new NSScreen(screens.objectAtIndex(0));
1423         NSRect frame = screen.frame();
1424         monitor.x = cast(int)frame.x;
1425         monitor.y = cast(int)(frame.height - (frame.y + frame.height));
1426         monitor.width = cast(int)frame.width;
1427         monitor.height = cast(int)frame.height;
1428         NSRect visibleFrame = screen.visibleFrame();
1429         monitor.clientX = cast(int)visibleFrame.x;
1430         monitor.clientY = cast(int)(frame.height - (visibleFrame.y + visibleFrame.height));
1431         monitor.clientWidth = cast(int)visibleFrame.width;
1432         monitor.clientHeight = cast(int)visibleFrame.height;
1433         return monitor;
1434     }
1435    
1436     /**
1437      * Returns a (possibly empty) array containing all shells which have
1438      * not been disposed and have the receiver as their display.
1439      *
1440      * @return the receiver's shells
1441      *
1442      * @exception DWTException <ul>
1443      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1444      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1445      * </ul>
1446      */
1447     public Shell [] getShells () {
1448         checkDevice ();
1449         NSArray windows = application.windows();
1450         int index = 0;
1451         Shell [] result = new Shell [windows.count()];
1452         for (int i = 0; i < result.length; i++) {
1453             NSWindow window = new NSWindow(windows.objectAtIndex(i));
1454             Widget widget = getWidget(window.contentView());
1455             if (cast(Shell) widget) {
1456                 result[index++] = cast(Shell)widget;
1457             }
1458         }
1459         if (index is result.length) return result;
1460         Shell [] newResult = new Shell [index];
1461         System.arraycopy (result, 0, newResult, 0, index);
1462         return newResult;
1463     }
1464    
1465     /**
1466      * Gets the synchronizer used by the display.
1467      *
1468      * @return the receiver's synchronizer
1469      *
1470      * @exception DWTException <ul>
1471      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1472      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1473      * </ul>
1474      *
1475      * @since 3.4
1476      */
1477     public Synchronizer getSynchronizer () {
1478         checkDevice ();
1479         return synchronizer;
1480     }
1481    
1482     /**
1483      * Returns the thread that has invoked <code>syncExec</code>
1484      * or null if no such runnable is currently being invoked by
1485      * the user-interface thread.
1486      * <p>
1487      * Note: If a runnable invoked by asyncExec is currently
1488      * running, this method will return null.
1489      * </p>
1490      *
1491      * @return the receiver's sync-interface thread
1492      *
1493      * @exception DWTException <ul>
1494      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1495      * </ul>
1496      */
1497     public Thread getSyncThread () {
1498         synchronized (Device.classinfo) {
1499             if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
1500             return synchronizer.syncThread;
1501         }
1502     }
1503    
1504     /**
1505      * Returns the matching standard color for the given
1506      * constant, which should be one of the color constants
1507      * specified in class <code>DWT</code>. Any value other
1508      * than one of the DWT color constants which is passed
1509      * in will result in the color black. This color should
1510      * not be free'd because it was allocated by the system,
1511      * not the application.
1512      *
1513      * @param id the color constant
1514      * @return the matching color
1515      *
1516      * @exception DWTException <ul>
1517      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1518      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1519      * </ul>
1520      *
1521      * @see DWT
1522      */
1523     public Color getSystemColor (int id) {
1524         checkDevice ();
1525         NSColor color = null;
1526         switch (id) {
1527             case DWT.COLOR_INFO_FOREGROUND: return super.getSystemColor (DWT.COLOR_BLACK);
1528             case DWT.COLOR_INFO_BACKGROUND: return Color.cocoa_new (this, [0xFF / 255f, 0xFF / 255f, 0xE1 / 255f, 1]);
1529             case DWT.COLOR_TITLE_FOREGROUND: color = NSColor.windowFrameTextColor(); break;
1530             case DWT.COLOR_TITLE_BACKGROUND: color = NSColor.secondarySelectedControlColor(); break;
1531             case DWT.COLOR_TITLE_BACKGROUND_GRADIENT: color = NSColor.windowFrameColor(); break;
1532             case DWT.COLOR_TITLE_INACTIVE_FOREGROUND: color = NSColor.disabledControlTextColor();  break;
1533             case DWT.COLOR_TITLE_INACTIVE_BACKGROUND: color = NSColor.secondarySelectedControlColor(); break;
1534             case DWT.COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT: color = NSColor.secondarySelectedControlColor(); break;
1535             case DWT.COLOR_WIDGET_DARK_SHADOW: color = NSColor.controlDarkShadowColor(); break;
1536             case DWT.COLOR_WIDGET_NORMAL_SHADOW: color = NSColor.controlShadowColor(); break;
1537             case DWT.COLOR_WIDGET_LIGHT_SHADOW: color = NSColor.controlHighlightColor(); break;
1538             case DWT.COLOR_WIDGET_HIGHLIGHT_SHADOW: color = NSColor.controlLightHighlightColor(); break;
1539             case DWT.COLOR_WIDGET_BACKGROUND: color = NSColor.controlHighlightColor(); break;
1540             case DWT.COLOR_WIDGET_FOREGROUND: color = NSColor.controlTextColor(); break;
1541             case DWT.COLOR_WIDGET_BORDER: return super.getSystemColor (DWT.COLOR_BLACK);
1542             case DWT.COLOR_LIST_FOREGROUND: color = NSColor.textColor(); break;
1543             case DWT.COLOR_LIST_BACKGROUND: color = NSColor.textBackgroundColor(); break;
1544             case DWT.COLOR_LIST_SELECTION_TEXT: color = NSColor.selectedTextColor(); break;
1545             case DWT.COLOR_LIST_SELECTION: color = NSColor.selectedTextBackgroundColor(); break;
1546             default:
1547                 return super.getSystemColor (id);   
1548         }
1549         if (color is null) return super.getSystemColor(id);
1550         color = color.colorUsingColorSpace(NSColorSpace.deviceRGBColorSpace());
1551         if (color is null) return super.getSystemColor(id);
1552         CGFloat[] components = new CGFloat[color.numberOfComponents()];
1553         color.getComponents(components.ptr);
1554         return Color.cocoa_new (this, [components[0], components[1], components[2], components[3]]);
1555     }
1556    
1557     /**
1558      * Returns the matching standard platform cursor for the given
1559      * constant, which should be one of the cursor constants
1560      * specified in class <code>DWT</code>. This cursor should
1561      * not be free'd because it was allocated by the system,
1562      * not the application.  A value of <code>null</code> will
1563      * be returned if the supplied constant is not an DWT cursor
1564      * constant.
1565      *
1566      * @param id the DWT cursor constant
1567      * @return the corresponding cursor or <code>null</code>
1568      *
1569      * @exception DWTException <ul>
1570      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1571      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1572      * </ul>
1573      *
1574      * @see DWT#CURSOR_ARROW
1575      * @see DWT#CURSOR_WAIT
1576      * @see DWT#CURSOR_CROSS
1577      * @see DWT#CURSOR_APPSTARTING
1578      * @see DWT#CURSOR_HELP
1579      * @see DWT#CURSOR_SIZEALL
1580      * @see DWT#CURSOR_SIZENESW
1581      * @see DWT#CURSOR_SIZENS
1582      * @see DWT#CURSOR_SIZENWSE
1583      * @see DWT#CURSOR_SIZEWE
1584      * @see DWT#CURSOR_SIZEN
1585      * @see DWT#CURSOR_SIZES
1586      * @see DWT#CURSOR_SIZEE
1587      * @see DWT#CURSOR_SIZEW
1588      * @see DWT#CURSOR_SIZENE
1589      * @see DWT#CURSOR_SIZESE
1590      * @see DWT#CURSOR_SIZESW
1591      * @see DWT#CURSOR_SIZENW
1592      * @see DWT#CURSOR_UPARROW
1593      * @see DWT#CURSOR_IBEAM
1594      * @see DWT#CURSOR_NO
1595      * @see DWT#CURSOR_HAND
1596      *
1597      * @since 3.0
1598      */
1599     public Cursor getSystemCursor (int id) {
1600         checkDevice ();
1601         if (!(0 <= id && id < cursors.length)) return null;
1602         if (cursors [id] is null) {
1603             cursors [id] = new Cursor (this, id);
1604         }
1605         return cursors [id];
1606     }
1607    
1608     /**
1609      * Returns the matching standard platform image for the given
1610      * constant, which should be one of the icon constants
1611      * specified in class <code>DWT</code>. This image should
1612      * not be free'd because it was allocated by the system,
1613      * not the application.  A value of <code>null</code> will
1614      * be returned either if the supplied constant is not an
1615      * DWT icon constant or if the platform does not define an
1616      * image that corresponds to the constant.
1617      *
1618      * @param id the DWT icon constant
1619      * @return the corresponding image or <code>null</code>
1620      *
1621      * @exception DWTException <ul>
1622      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1623      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1624      * </ul>
1625      *
1626      * @see DWT#ICON_ERROR
1627      * @see DWT#ICON_INFORMATION
1628      * @see DWT#ICON_QUESTION
1629      * @see DWT#ICON_WARNING
1630      * @see DWT#ICON_WORKING
1631      *
1632      * @since 3.0
1633      */
1634     public Image getSystemImage (int id) {
1635         checkDevice ();
1636         switch(id) {
1637             case DWT.ICON_ERROR: { 
1638                 if (errorImage !is null) return errorImage;
1639                 NSImage nsImage = NSWorkspace.sharedWorkspace ().iconForFileType (new NSString (OS.NSFileTypeForHFSTypeCode (OS.kAlertStopIcon)));
1640                 if (nsImage is null) return null;
1641                 nsImage.retain ();
1642                 return errorImage = Image.cocoa_new (this, DWT.ICON, nsImage);
1643             }
1644             case DWT.ICON_INFORMATION:
1645             case DWT.ICON_QUESTION:
1646             case DWT.ICON_WORKING: {
1647                 if (infoImage !is null) return infoImage;
1648                 NSImage nsImage = NSWorkspace.sharedWorkspace ().iconForFileType (new NSString (OS.NSFileTypeForHFSTypeCode (OS.kAlertNoteIcon)));
1649                 if (nsImage is null) return null;
1650                 nsImage.retain ();
1651                 return infoImage = Image.cocoa_new (this, DWT.ICON, nsImage);
1652             }
1653             case DWT.ICON_WARNING: {
1654                 if (warningImage !is null) return warningImage;
1655                 NSImage nsImage = NSWorkspace.sharedWorkspace ().iconForFileType (new NSString (OS.NSFileTypeForHFSTypeCode (OS.kAlertCautionIcon)));
1656                 if (nsImage is null) return null;
1657                 nsImage.retain ();
1658                 return warningImage = Image.cocoa_new (this, DWT.ICON, nsImage);
1659             }
1660                
1661             default:
1662         }
1663         return null;
1664     }
1665    
1666     /**
1667      * Returns the single instance of the system tray or null
1668      * when there is no system tray available for the platform.
1669      *
1670      * @return the system tray or <code>null</code>
1671      *
1672      * @exception DWTException <ul>
1673      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1674      * </ul>
1675      *
1676      * @since 3.0
1677      */
1678     public Tray getSystemTray () {
1679         checkDevice ();
1680         if (tray !is null) return tray;
1681         return tray = new Tray (this, DWT.NONE);
1682     }
1683    
1684     /**
1685      * Returns the user-interface thread for the receiver.
1686      *
1687      * @return the receiver's user-interface thread
1688      *
1689      * @exception DWTException <ul>
1690      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
1691      * </ul>
1692      */
1693     public Thread getThread () {
1694         synchronized (Device.classinfo) {
1695             if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
1696             return thread;
1697         }
1698     }
1699    
1700     int getToolTipTime () {
1701         checkDevice ();
1702         //TODO get OS value (NSTooltipManager?)
1703         return 560;
1704     }
1705    
1706     Widget getWidget (objc.id id) {
1707         return GetWidget (id);
1708     }
1709    
1710     static Widget GetWidget (objc.id id) {
1711         if (id is null) return null;
1712         void* jniRef;
1713         OS.object_getInstanceVariable(id, SWT_OBJECT, jniRef);
1714         if (jniRef is null) return null;
1715         return cast(Widget)OS.JNIGetObject(jniRef);
1716     }
1717    
1718     Widget getWidget (NSView view) {
1719         if (view is null) return null;
1720         return getWidget(view.id);
1721     }
1722    
1723     /**
1724      * Initializes any internal resources needed by the
1725      * device.
1726      * <p>
1727      * This method is called after <code>create</code>.
1728      * </p>
1729      *
1730      * @see #create
1731      */
1732     protected void init_ () {
1733         super.init_ ();
1734         initClasses ();
1735        
1736         if (!isEmbedded) {
1737             initApplicationDelegate(); 
1738             application.finishLaunching();
1739          }
1740          
1741          timerDelegate = cast(SWTWindowDelegate)(new SWTWindowDelegate()).alloc().init();
1742          
1743          NSTextView textView = cast(NSTextView)(new NSTextView()).alloc();
1744          textView.initWithFrame (NSRect ());
1745          markedAttributes = textView.markedTextAttributes ();
1746          markedAttributes.retain ();
1747          textView.release ();
1748     }
1749    
1750     void initApplicationDelegate() {
1751         String className = "SWTApplicationDelegate";
1752         if (OS.objc_lookUpClass (className) is null) {
1753             objc.IMP appProc3 = cast(objc.IMP) &applicationDelegateProc;
1754             objc.Class cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSObject, className, 0);
1755             OS.class_addMethod(cls, OS.sel_applicationWillFinishLaunching_, appProc3, "@:@");
1756             OS.class_addMethod(cls, OS.sel_terminate_, appProc3, "@:@");
1757             OS.class_addMethod(cls, OS.sel_orderFrontStandardAboutPanel_, appProc3, "@:@");
1758             OS.class_addMethod(cls, OS.sel_hideOtherApplications_, appProc3, "@:@");
1759             OS.class_addMethod(cls, OS.sel_hide_, appProc3, "@:@");
1760             OS.class_addMethod(cls, OS.sel_unhideAllApplications_, appProc3, "@:@");
1761             OS.class_addMethod(cls, OS.sel_applicationShouldTerminate_, appProc3, "@:@");
1762             OS.class_addMethod(cls, OS.sel_applicationWillTerminate_, appProc3, "@:@");
1763             OS.class_addMethod(cls, OS.sel_applicationWillResignActive_, appProc3, "@:@");
1764             OS.objc_registerClassPair(cls);
1765         }   
1766         applicationDelegate = cast(SWTApplicationDelegate)(new SWTApplicationDelegate()).alloc().init();   
1767         application.setDelegate(applicationDelegate);
1768     }
1769    
1770     void addEventMethods (objc.Class cls, objc.IMP proc2, objc.IMP proc3, objc.IMP drawRectProc) {
1771         OS.class_addMethod(cls, OS.sel_mouseDown_, proc3, "@:@");
1772         OS.class_addMethod(cls, OS.sel_mouseUp_, proc3, "@:@");
1773         OS.class_addMethod(cls, OS.sel_scrollWheel_, proc3, "@:@");
1774         OS.class_addMethod(cls, OS.sel_rightMouseDown_, proc3, "@:@");
1775         OS.class_addMethod(cls, OS.sel_rightMouseUp_, proc3, "@:@");
1776         OS.class_addMethod(cls, OS.sel_otherMouseDown_, proc3, "@:@");
1777         OS.class_addMethod(cls, OS.sel_otherMouseUp_, proc3, "@:@");
1778         OS.class_addMethod(cls, OS.sel_mouseDragged_, proc3, "@:@");
1779         OS.class_addMethod(cls, OS.sel_mouseMoved_, proc3, "@:@");
1780         OS.class_addMethod(cls, OS.sel_mouseEntered_, proc3, "@:@");
1781         OS.class_addMethod(cls, OS.sel_mouseExited_, proc3, "@:@");
1782         OS.class_addMethod(cls, OS.sel_menuForEvent_, proc3, "@:@");
1783         OS.class_addMethod(cls, OS.sel_resignFirstResponder, proc2, "@:");
1784         OS.class_addMethod(cls, OS.sel_becomeFirstResponder, proc2, "@:");
1785         OS.class_addMethod(cls, OS.sel_keyDown_, proc3, "@:@");
1786         OS.class_addMethod(cls, OS.sel_keyUp_, proc3, "@:@");
1787         OS.class_addMethod(cls, OS.sel_flagsChanged_, proc3, "@:@");
1788         OS.class_addMethod(cls, OS.sel_drawRect_, drawRectProc, "@:{NSRect}");
1789     }
1790    
1791     void addFrameMethods(objc.Class cls, objc.IMP setFrameOriginProc, objc.IMP setFrameSizeProc) {
1792         OS.class_addMethod(cls, OS.sel_setFrameOrigin_, setFrameOriginProc, "@:{NSPoint}");
1793         OS.class_addMethod(cls, OS.sel_setFrameSize_, setFrameSizeProc, "@:{NSSize}"); 
1794     }
1795    
1796     void addAccessibilityMethods(objc.Class cls, objc.IMP proc2, objc.IMP proc3, objc.IMP proc4, objc.IMP accessibilityHitTestProc) {
1797         OS.class_addMethod(cls, OS.sel_accessibilityActionNames, proc2, "@:");
1798         OS.class_addMethod(cls, OS.sel_accessibilityAttributeNames, proc2, "@:");
1799         OS.class_addMethod(cls, OS.sel_accessibilityParameterizedAttributeNames, proc2, "@:");
1800         OS.class_addMethod(cls, OS.sel_accessibilityFocusedUIElement, proc2, "@:");
1801         OS.class_addMethod(cls, OS.sel_accessibilityIsIgnored, proc2, "@:");
1802         OS.class_addMethod(cls, OS.sel_accessibilityAttributeValue_, proc3, "@:@");
1803         OS.class_addMethod(cls, OS.sel_accessibilityIsAttributeSettable_, proc3, "@:@");
1804         OS.class_addMethod(cls, OS.sel_accessibilityHitTest_, accessibilityHitTestProc, "@:{NSPoint}");
1805         OS.class_addMethod(cls, OS.sel_accessibilityAttributeValue_forParameter_, proc4, "@:@@");   
1806         OS.class_addMethod(cls, OS.sel_accessibilityPerformAction_, proc3, "@:@"); 
1807         OS.class_addMethod(cls, OS.sel_accessibilityActionDescription_, proc3, "@:@"); 
1808     }
1809    
1810     objc.Class registerCellSubclass(objc.Class cellClass, int size, int align_, String types) {
1811         String cellClassName = OS.class_getName(cellClass);
1812         objc.Class cls = OS.objc_allocateClassPair(cellClass, "SWT" ~ cellClassName, 0);   
1813         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
1814         OS.objc_registerClassPair(cls);
1815         return cls;
1816     }
1817    
1818     void initClasses () {
1819         if (OS.objc_lookUpClass ("SWTView") !is null) return;
1820        
1821         objc.IMP dialogProc3 = cast(objc.IMP) &dialogProc;
1822         objc.IMP proc3 = cast(objc.IMP) &windowDelegateProc3;
1823         objc.IMP proc2 = cast(objc.IMP) &windowDelegateProc2;
1824         objc.IMP proc4 = cast(objc.IMP) &windowDelegateProc4;
1825         objc.IMP proc5 = cast(objc.IMP) &windowDelegateProc5;
1826         objc.IMP proc6 = cast(objc.IMP) &windowDelegateProc6;
1827        
1828         objc.IMP drawRectProc = OS.drawRect_CALLBACK(proc3);
1829         objc.IMP drawInteriorWithFrameInViewProc = OS.drawInteriorWithFrame_inView_CALLBACK (proc4);
1830         objc.IMP setFrameOriginProc = OS.setFrameOrigin_CALLBACK(proc3);
1831         objc.IMP setFrameSizeProc = OS.setFrameSize_CALLBACK(proc3);
1832         objc.IMP hitTestProc = OS.hitTest_CALLBACK(proc3);
1833         objc.IMP markedRangeProc = OS.markedRange_CALLBACK(proc2);
1834         objc.IMP selectedRangeProc = OS.selectedRange_CALLBACK(proc2);
1835         objc.IMP highlightSelectionInClipRectProc = OS.highlightSelectionInClipRect_CALLBACK(proc3);
1836         objc.IMP setMarkedText_selectedRangeProc = OS.setMarkedText_selectedRange_CALLBACK(proc4);
1837         objc.IMP attributedSubstringFromRangeProc = OS.attributedSubstringFromRange_CALLBACK(proc3);
1838         objc.IMP characterIndexForPointProc = OS.characterIndexForPoint_CALLBACK(proc3);
1839         objc.IMP firstRectForCharacterRangeProc = OS.firstRectForCharacterRange_CALLBACK(proc3);   
1840         objc.IMP textWillChangeSelectionProc = OS.textView_willChangeSelectionFromCharacterRange_toCharacterRange_CALLBACK(proc5);
1841         objc.IMP accessibilityHitTestProc = OS.accessibilityHitTest_CALLBACK(proc3);
1842        
1843         String types = "*";
1844         size_t size = C.PTR_SIZEOF, align_ = C.PTR_SIZEOF is 4 ? 2 : 3;
1845        
1846         String className = "SWTWindowDelegate";
1847         objc.Class cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSObject, className, 0);
1848         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
1849         OS.class_addMethod(cls, OS.sel_windowDidResize_, proc3, "@:@");
1850         OS.class_addMethod(cls, OS.sel_windowDidMove_, proc3, "@:@");
1851         OS.class_addMethod(cls, OS.sel_windowShouldClose_, proc3, "@:@");
1852         OS.class_addMethod(cls, OS.sel_windowWillClose_, proc3, "@:@");
1853         OS.class_addMethod(cls, OS.sel_windowDidResignKey_, proc3, "@:@");
1854         OS.class_addMethod(cls, OS.sel_windowDidBecomeKey_, proc3, "@:@");
1855         OS.class_addMethod(cls, OS.sel_timerProc_, proc3, "@:@");
1856         OS.objc_registerClassPair(cls);
1857        
1858         className = "SWTPanelDelegate";
1859         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSObject, className, 0);
1860         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
1861         OS.class_addMethod(cls, OS.sel_windowWillClose_, dialogProc3, "@:@");
1862         OS.class_addMethod(cls, OS.sel_changeColor_, dialogProc3, "@:@");
1863         OS.class_addMethod(cls, OS.sel_changeFont_, dialogProc3, "@:@");
1864         OS.objc_registerClassPair(cls);
1865        
1866         className = "SWTMenu";
1867         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSMenu, className, 0);
1868         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
1869         OS.class_addMethod(cls, OS.sel_menuWillOpen_, proc3, "@:@");
1870         OS.class_addMethod(cls, OS.sel_menuDidClose_, proc3, "@:@");
1871         OS.class_addMethod(cls, OS.sel_menu_willHighlightItem_, proc4, "@:@@");
1872         OS.class_addMethod(cls, OS.sel_menuNeedsUpdate_, proc3, "@:@");
1873         OS.objc_registerClassPair(cls);
1874        
1875         className = "SWTView";
1876         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSView, className, 0);
1877         OS.class_addProtocol(cls, OS.objc_getProtocol("NSTextInput"));
1878         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
1879         OS.class_addMethod(cls, OS.sel_isFlipped, proc2, "@:");
1880         OS.class_addMethod(cls, OS.sel_acceptsFirstResponder, proc2, "@:");
1881         OS.class_addMethod(cls, OS.sel_isOpaque, proc2, "@:");
1882         OS.class_addMethod(cls, OS.sel_hitTest_, hitTestProc, "@:{NSPoint}");
1883        
1884         //NSTextInput protocol
1885         OS.class_addMethod(cls, OS.sel_hasMarkedText, proc2, "@:");
1886         OS.class_addMethod(cls, OS.sel_markedRange, markedRangeProc, "@:");
1887         OS.class_addMethod(cls, OS.sel_selectedRange, selectedRangeProc, "@:");
1888         OS.class_addMethod(cls, OS.sel_setMarkedText_selectedRange_, setMarkedText_selectedRangeProc, "@:@{NSRange}");
1889         OS.class_addMethod(cls, OS.sel_unmarkText, proc2, "@:");
1890         OS.class_addMethod(cls, OS.sel_validAttributesForMarkedText, proc2, "@:");
1891         OS.class_addMethod(cls, OS.sel_attributedSubstringFromRange_, attributedSubstringFromRangeProc, "@:{NSRange}");
1892         OS.class_addMethod(cls, OS.sel_insertText_, proc3, "@:@");
1893         OS.class_addMethod(cls, OS.sel_characterIndexForPoint_, characterIndexForPointProc, "@:{NSPoint}");
1894         OS.class_addMethod(cls, OS.sel_firstRectForCharacterRange_, firstRectForCharacterRangeProc, "@:{NSRange}");
1895         OS.class_addMethod(cls, OS.sel_doCommandBySelector_, proc3, "@::");
1896        
1897         addEventMethods(cls, proc2, proc3, drawRectProc);
1898         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
1899         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
1900         OS.objc_registerClassPair(cls);
1901        
1902         className = "SWTScrollView";
1903         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSScrollView, className, 0);
1904         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
1905         OS.class_addMethod(cls, OS.sel_sendVerticalSelection, proc2, "@:");
1906         OS.class_addMethod(cls, OS.sel_sendHorizontalSelection, proc2, "@:");
1907         OS.class_addMethod(cls, OS.sel_pageDown_, proc3, "@:@");
1908         OS.class_addMethod(cls, OS.sel_pageUp_, proc3, "@:@");
1909         OS.class_addMethod(cls, OS.sel_reflectScrolledClipView_, proc3, "@:@");
1910         addEventMethods(cls, proc2, proc3, drawRectProc);
1911         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
1912         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
1913         OS.objc_registerClassPair(cls);
1914        
1915         className = "SWTButton";
1916         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSButton, className, 0);
1917         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
1918         OS.class_addMethod(cls, OS.sel_sendSelection, proc2, "@:");
1919         addEventMethods(cls, proc2, proc3, drawRectProc);
1920         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
1921         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
1922         OS.objc_registerClassPair(cls);
1923        
1924         cls = registerCellSubclass(NSButton.cellClass(), size, align_, types);
1925         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);   
1926         NSButton.setCellClass(cls);
1927        
1928         className = "SWTTableView";
1929         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSTableView, className, 0);
1930         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
1931         OS.class_addMethod(cls, OS.sel_highlightSelectionInClipRect_, highlightSelectionInClipRectProc, "@:{NSRect}");
1932         OS.class_addMethod(cls, OS.sel_sendDoubleSelection, proc2, "@:");
1933         OS.class_addMethod(cls, OS.sel_numberOfRowsInTableView_, proc3, "@:@");
1934         OS.class_addMethod(cls, OS.sel_tableView_objectValueForTableColumn_row_, proc5, "@:@:@:@");
1935         OS.class_addMethod(cls, OS.sel_tableView_shouldEditTableColumn_row_, proc5, "@:@:@:@");
1936         OS.class_addMethod(cls, OS.sel_tableViewSelectionDidChange_, proc3, "@:@");
1937         static if ((void*).sizeof > int.sizeof) /* 64bit target*/ OS.class_addMethod(cls, OS.sel_tableView_willDisplayCell_forTableColumn_row_, proc6, "@:@@@q");
1938         else OS.class_addMethod(cls, OS.sel_tableView_willDisplayCell_forTableColumn_row_, proc6, "@:@@@i");
1939         static if ((void*).sizeof > int.sizeof) /* 64bit target*/ OS.class_addMethod(cls, OS.sel_tableView_setObjectValue_forTableColumn_row_, proc6, "@:@@@q");
1940         else OS.class_addMethod(cls, OS.sel_tableView_setObjectValue_forTableColumn_row_, proc6, "@:@@@i");
1941         OS.class_addMethod(cls, OS.sel_tableViewColumnDidMove_, proc3, "@:@");
1942         OS.class_addMethod(cls, OS.sel_tableViewColumnDidResize_, proc3, "@:@");
1943         OS.class_addMethod(cls, OS.sel_tableView_didClickTableColumn_, proc4, "@:@");
1944         addEventMethods(cls, proc2, proc3, drawRectProc);
1945         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
1946         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
1947         OS.objc_registerClassPair(cls);
1948        
1949         className = "SWTTableHeaderCell";
1950         cls = OS.objc_allocateClassPair (cast(objc.Class) OS.class_NSTableHeaderCell, className, 0);
1951         OS.class_addIvar (cls, SWT_OBJECT, size, cast(byte)align_, types);
1952         OS.class_addMethod (cls, OS.sel_drawInteriorWithFrame_inView_, drawInteriorWithFrameInViewProc, "@:{NSRect}@");
1953         OS.objc_registerClassPair (cls);
1954        
1955         className = "SWTBrowserCell";
1956         cls = OS.objc_allocateClassPair (cast(objc.Class) OS.class_NSBrowserCell, className, 0);
1957         OS.class_addIvar (cls, SWT_OBJECT, size, cast(byte)align_, types);
1958         OS.class_addMethod (cls, OS.sel_drawInteriorWithFrame_inView_, drawInteriorWithFrameInViewProc, "@:{NSRect}@");
1959         OS.objc_registerClassPair (cls);
1960        
1961         className = "SWTTableHeaderView";
1962         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSTableHeaderView, className, 0);
1963         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
1964         OS.class_addMethod(cls, OS.sel_mouseDown_, proc3, "@:@");
1965         OS.objc_registerClassPair(cls);
1966        
1967         className = "SWTOutlineView";
1968         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSOutlineView, className, 0);
1969         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
1970         OS.class_addMethod(cls, OS.sel_highlightSelectionInClipRect_, highlightSelectionInClipRectProc, "@:{NSRect}");
1971         OS.class_addMethod(cls, OS.sel_sendDoubleSelection, proc2, "@:");
1972         OS.class_addMethod(cls, OS.sel_outlineViewSelectionDidChange_, proc3, "@:@");
1973         OS.class_addMethod(cls, OS.sel_outlineViewItemDidExpand_, proc3, "@:@");
1974         OS.class_addMethod(cls, OS.sel_outlineView_shouldCollapseItem_, proc4, "@:@@");
1975         OS.class_addMethod(cls, OS.sel_outlineView_shouldExpandItem_, proc4, "@:@@");
1976         OS.class_addMethod(cls, OS.sel_outlineView_child_ofItem_, proc5, "@:@i@");
1977         OS.class_addMethod(cls, OS.sel_outlineView_isItemExpandable_, proc4, "@:@@");
1978         OS.class_addMethod(cls, OS.sel_outlineView_numberOfChildrenOfItem_, proc4, "@:@@");
1979         OS.class_addMethod(cls, OS.sel_outlineView_objectValueForTableColumn_byItem_, proc5, "@:@@@");
1980         OS.class_addMethod(cls, OS.sel_outlineView_willDisplayCell_forTableColumn_item_, proc6, "@:@@@@");
1981         OS.class_addMethod(cls, OS.sel_outlineView_setObjectValue_forTableColumn_byItem_, proc6, "@:@@@@");
1982         OS.class_addMethod(cls, OS.sel_outlineViewColumnDidMove_, proc3, "@:@");
1983         OS.class_addMethod(cls, OS.sel_outlineViewColumnDidResize_, proc3, "@:@");
1984         OS.class_addMethod(cls, OS.sel_outlineView_didClickTableColumn_, proc4, "@:@");
1985         addEventMethods(cls, proc2, proc3, drawRectProc);
1986         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
1987         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
1988         OS.objc_registerClassPair(cls);
1989        
1990         className = "SWTTreeItem";
1991         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSObject, className, 0);
1992         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
1993         OS.objc_registerClassPair(cls);
1994        
1995         className = "SWTTabView";
1996         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSTabView, className, 0);
1997         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
1998         OS.class_addMethod(cls, OS.sel_tabView_willSelectTabViewItem_, proc4, "@:@@");
1999         OS.class_addMethod(cls, OS.sel_tabView_didSelectTabViewItem_, proc4, "@:@@");
2000         addEventMethods(cls, proc2, proc3, drawRectProc);
2001         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
2002         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
2003         OS.objc_registerClassPair(cls);
2004        
2005         className = "SWTBox";
2006         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSBox, className, 0);
2007         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
2008         addEventMethods(cls, proc2, proc3, drawRectProc);
2009         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
2010         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
2011         OS.objc_registerClassPair(cls);
2012        
2013         className = "SWTProgressIndicator";
2014         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSProgressIndicator, className, 0);
2015         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
2016         addEventMethods(cls, proc2, proc3, drawRectProc);
2017         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
2018         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
2019         OS.objc_registerClassPair(cls);
2020        
2021         className = "SWTSlider";
2022         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSSlider, className, 0);
2023         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
2024         addEventMethods(cls, proc2, proc3, drawRectProc);
2025         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
2026         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
2027         OS.objc_registerClassPair(cls);
2028        
2029         cls = registerCellSubclass(NSSlider.cellClass(), size, align_, types);
2030         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);   
2031         NSSlider.setCellClass(cls);
2032        
2033         className = "SWTPopUpButton";
2034         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSPopUpButton, className, 0);
2035         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
2036         OS.class_addMethod(cls, OS.sel_sendSelection, proc2, "@:");
2037         addEventMethods(cls, proc2, proc3, drawRectProc);
2038         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
2039         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
2040         OS.objc_registerClassPair(cls);
2041        
2042         cls = registerCellSubclass(NSPopUpButton.cellClass(), size, align_, types);
2043         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);   
2044         NSPopUpButton.setCellClass(cls);
2045        
2046         className = "SWTComboBox";
2047         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSComboBox, className, 0);
2048         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
2049         OS.class_addMethod(cls, OS.sel_comboBoxSelectionDidChange_, proc3, "@:@");
2050         OS.class_addMethod(cls, OS.sel_sendSelection, proc2, "@:");
2051         OS.class_addMethod(cls, OS.sel_textDidChange_, proc3, "@:@");
2052         OS.class_addMethod(cls, OS.sel_textViewDidChangeSelection_, proc3, "@:@");
2053         OS.class_addMethod(cls, OS.sel_textView_willChangeSelectionFromCharacterRange_toCharacterRange_, textWillChangeSelectionProc, "@:@{NSRange}{NSRange}");
2054         addEventMethods(cls, proc2, proc3, drawRectProc);
2055         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
2056         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
2057         OS.objc_registerClassPair(cls);
2058        
2059         cls = registerCellSubclass(NSComboBox.cellClass(), size, align_, types);
2060         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);   
2061         NSComboBox.setCellClass(cls);
2062        
2063         className = "SWTDatePicker";
2064         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSDatePicker, className, 0);
2065         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
2066         OS.class_addMethod(cls, OS.sel_sendSelection, proc2, "@:");
2067         addEventMethods(cls, proc2, proc3, drawRectProc);
2068         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
2069         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
2070         OS.objc_registerClassPair(cls);
2071        
2072         className = "SWTImageView";
2073         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSImageView, className, 0);
2074         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
2075         addEventMethods(cls, proc2, proc3, drawRectProc);
2076         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
2077         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
2078         OS.objc_registerClassPair(cls);
2079        
2080         cls = registerCellSubclass(NSImageView.cellClass(), size, align_, types);
2081         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);   
2082         NSImageView.setCellClass(cls);
2083        
2084         className = "SWTStepper";
2085         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSStepper, className, 0);
2086         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
2087         OS.class_addMethod(cls, OS.sel_sendSelection, proc2, "@:");
2088         addEventMethods(cls, proc2, proc3, drawRectProc);
2089         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
2090         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
2091         OS.objc_registerClassPair(cls);
2092        
2093         cls = registerCellSubclass(NSStepper.cellClass(), size, align_, types);
2094         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);   
2095         NSStepper.setCellClass(cls);
2096        
2097         className = "SWTScroller";
2098         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSScroller, className, 0);
2099         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
2100         OS.class_addMethod(cls, OS.sel_sendSelection, proc2, "@:");
2101         addEventMethods(cls, proc2, proc3, drawRectProc);
2102         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
2103         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
2104         OS.objc_registerClassPair(cls);
2105        
2106         className = "SWTMenuItem";
2107         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSMenuItem, className, 0);
2108         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
2109         OS.class_addMethod(cls, OS.sel_sendSelection, proc2, "@:");
2110         OS.objc_registerClassPair(cls);
2111        
2112         className = "SWTTextView";
2113         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSTextView, className, 0);
2114         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
2115         addEventMethods(cls, proc2, proc3, drawRectProc);
2116         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
2117         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
2118         OS.class_addMethod(cls, OS.sel_insertText_, proc3, "@:@");
2119         OS.class_addMethod(cls, OS.sel_doCommandBySelector_, proc3, "@::");
2120         OS.class_addMethod(cls, OS.sel_textDidChange_, proc3, "@:@");
2121         OS.class_addMethod(cls, OS.sel_textView_clickedOnLink_atIndex_, proc5, "@:@@@");
2122         OS.objc_registerClassPair(cls);
2123        
2124         className = "SWTEditorView";
2125         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSTextView, className, 0);
2126         OS.class_addMethod(cls, OS.sel_keyDown_, proc3, "@:@");
2127         OS.class_addMethod(cls, OS.sel_keyUp_, proc3, "@:@");
2128         OS.class_addMethod(cls, OS.sel_insertText_, proc3, "@:@");
2129         OS.class_addMethod(cls, OS.sel_doCommandBySelector_, proc3, "@::");
2130         OS.objc_registerClassPair(cls);
2131        
2132         className = "SWTTextField";
2133         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSTextField, className, 0);
2134         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
2135         addEventMethods(cls, proc2, proc3, drawRectProc);
2136         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
2137         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
2138         OS.class_addMethod(cls, OS.sel_textDidChange_, proc3, "@:@");
2139         OS.class_addMethod(cls, OS.sel_textViewDidChangeSelection_, proc3, "@:@");
2140         OS.class_addMethod(cls, OS.sel_textView_willChangeSelectionFromCharacterRange_toCharacterRange_, textWillChangeSelectionProc, "@:@{NSRange}{NSRange}");
2141         OS.objc_registerClassPair(cls);
2142        
2143         cls = registerCellSubclass(NSTextField.cellClass(), size, align_, types);
2144         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);   
2145         NSTextField.setCellClass(cls);
2146        
2147         className = "SWTSearchField";
2148         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSSearchField, className, 0);
2149         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
2150         addEventMethods(cls, proc2, proc3, drawRectProc);
2151         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
2152         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
2153         OS.class_addMethod(cls, OS.sel_textDidChange_, proc3, "@:@");
2154         OS.class_addMethod(cls, OS.sel_textViewDidChangeSelection_, proc3, "@:@");
2155         OS.class_addMethod(cls, OS.sel_textView_willChangeSelectionFromCharacterRange_toCharacterRange_, textWillChangeSelectionProc, "@:@{NSRange}{NSRange}");
2156         OS.objc_registerClassPair(cls);
2157        
2158         cls = registerCellSubclass(NSSearchField.cellClass(), size, align_, types);
2159         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);   
2160         NSSearchField.setCellClass(cls);
2161        
2162         className = "SWTSecureTextField";
2163         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSSecureTextField, className, 0);
2164         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
2165         addEventMethods(cls, proc2, proc3, drawRectProc);
2166         addFrameMethods(cls, setFrameOriginProc, setFrameSizeProc);
2167         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
2168         OS.class_addMethod(cls, OS.sel_textDidChange_, proc3, "@:@");
2169         OS.class_addMethod(cls, OS.sel_textViewDidChangeSelection_, proc3, "@:@");
2170         OS.class_addMethod(cls, OS.sel_textView_willChangeSelectionFromCharacterRange_toCharacterRange_, textWillChangeSelectionProc, "@:@{NSRange}{NSRange}");
2171         OS.objc_registerClassPair(cls);
2172        
2173         // Don't subclass NSSecureTextFieldCell -- you'll get an NSException from [NSSecureTextField setCellClass:]!
2174        
2175         className = "SWTWindow";
2176         cls = OS.objc_allocateClassPair(cast(objc.Class) OS.class_NSWindow, className, 0);
2177         OS.class_addIvar(cls, SWT_OBJECT, size, cast(byte)align_, types);
2178         OS.class_addMethod(cls, OS.sel_sendEvent_, proc3, "@:@");
2179         OS.class_addMethod(cls, OS.sel_helpRequested_, proc3, "@:@");
2180         OS.class_addMethod(cls, OS.sel_canBecomeKeyWindow, proc2, "@:");
2181         OS.class_addMethod(cls, OS.sel_makeFirstResponder_, proc3, "@:@");
2182         addAccessibilityMethods(cls, proc2, proc3, proc4, accessibilityHitTestProc);
2183         OS.objc_registerClassPair(cls);
2184     }
2185    
2186     /** 
2187      * Invokes platform specific functionality to allocate a new GC handle.
2188      * <p>
2189      * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
2190      * API for <code>Display</code>. It is marked public only so that it
2191      * can be shared within the packages provided by DWT. It is not
2192      * available on all platforms, and should never be called from
2193      * application code.
2194      * </p>
2195      *
2196      * @param data the platform specific GC data
2197      * @return the platform specific GC handle
2198      *
2199      * @exception DWTException <ul>
2200      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2201      * </ul>
2202      * @exception DWTError <ul>
2203      *    <li>ERROR_NO_HANDLES if a handle could not be obtained for gc creation</li>
2204      * </ul>
2205      */
2206     public objc.id internal_new_GC (GCData data) {
2207         if (isDisposed()) DWT.error(DWT.ERROR_DEVICE_DISPOSED);
2208         if (screenWindow is null) {
2209             NSWindow window = cast(NSWindow) (new NSWindow ()).alloc ();
2210             NSRect rect = NSRect();
2211             window = window.initWithContentRect(rect, OS.NSBorderlessWindowMask, OS.NSBackingStoreBuffered, false);
2212             window.setReleasedWhenClosed(false);
2213             screenWindow = window;
2214         }
2215         NSGraphicsContext context = screenWindow.graphicsContext();
2216         //  NSAffineTransform transform = NSAffineTransform.transform();
2217         //  NSSize size = handle.size();
2218         //  transform.translateXBy(0, size.height);
2219         //  transform.scaleXBy(1, -1);
2220         //  transform.set();
2221         if (data !is null) {
2222             int mask = DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT;
2223             if ((data.style & mask) is 0) {
2224                 data.style |= DWT.LEFT_TO_RIGHT;
2225             }
2226             data.device = this;
2227             data.background = getSystemColor(DWT.COLOR_WHITE).handle;
2228             data.foreground = getSystemColor(DWT.COLOR_BLACK).handle;
2229             data.font = getSystemFont();
2230         }
2231         return context.id;
2232     }
2233    
2234     /** 
2235      * Invokes platform specific functionality to dispose a GC handle.
2236      * <p>
2237      * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
2238      * API for <code>Display</code>. It is marked public only so that it
2239      * can be shared within the packages provided by DWT. It is not
2240      * available on all platforms, and should never be called from
2241      * application code.
2242      * </p>
2243      *
2244      * @param hDC the platform specific GC handle
2245      * @param data the platform specific GC data
2246      */
2247     public void internal_dispose_GC (objc.id context, GCData data) {
2248         if (isDisposed()) DWT.error(DWT.ERROR_DEVICE_DISPOSED);
2249        
2250     }
2251    
2252     static bool isValidClass (ClassInfo clazz) {
2253         String name = clazz.name;
2254         int index = name.lastIndexOf ('.');
2255         name = name[0 .. index];
2256         index = name.lastIndexOf ('.');
2257         return name.substring (0, index + 1).equals (PACKAGE_PREFIX);
2258     }
2259    
2260     bool isValidThread () {
2261         return thread is Thread.getThis ();
2262     }
2263    
2264     /**
2265      * Generate a low level system event.
2266      *
2267      * <code>post</code> is used to generate low level keyboard
2268      * and mouse events. The intent is to enable automated UI
2269      * testing by simulating the input from the user.  Most
2270      * DWT applications should never need to call this method.
2271      * <p>
2272      * Note that this operation can fail when the operating system
2273      * fails to generate the event for any reason.  For example,
2274      * this can happen when there is no such key or mouse button
2275      * or when the system event queue is full.
2276      * </p>
2277      * <p>
2278      * <b>Event Types:</b>
2279      * <p>KeyDown, KeyUp
2280      * <p>The following fields in the <code>Event</code> apply:
2281      * <ul>
2282      * <li>(in) type KeyDown or KeyUp</li>
2283      * <p> Either one of:
2284      * <li>(in) character a character that corresponds to a keyboard key</li>
2285      * <li>(in) keyCode the key code of the key that was typed,
2286      *          as defined by the key code constants in class <code>DWT</code></li>
2287      * </ul>
2288      * <p>MouseDown, MouseUp</p>
2289      * <p>The following fields in the <code>Event</code> apply:
2290      * <ul>
2291      * <li>(in) type MouseDown or MouseUp
2292      * <li>(in) button the button that is pressed or released
2293      * </ul>
2294      * <p>MouseMove</p>
2295      * <p>The following fields in the <code>Event</code> apply:
2296      * <ul>
2297      * <li>(in) type MouseMove
2298      * <li>(in) x the x coordinate to move the mouse pointer to in screen coordinates
2299      * <li>(in) y the y coordinate to move the mouse pointer to in screen coordinates
2300      * </ul>
2301      * </dl>
2302      *
2303      * @param event the event to be generated
2304      *
2305      * @return true if the event was generated or false otherwise
2306      *
2307      * @exception IllegalArgumentException <ul>
2308      *    <li>ERROR_NULL_ARGUMENT - if the event is null</li>
2309      * </ul>
2310      * @exception DWTException <ul>
2311      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2312      * </ul>
2313      *
2314      * @since 3.0
2315      *
2316      */
2317     public bool post(Event event) {
2318         synchronized (Device.classinfo) {
2319             if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
2320             if (event is null) error (DWT.ERROR_NULL_ARGUMENT);
2321             //      int type = event.type;
2322             //      switch (type) {
2323             //          case DWT.KeyDown:
2324             //          case DWT.KeyUp: {
2325             //              int vKey = Display.untranslateKey (event.keyCode);
2326             //              if (vKey !is 0) {
2327             //                  return OS.CGPostKeyboardEvent (0, vKey, type is DWT.KeyDown) is 0;
2328             //              } else {
2329             //                  vKey = -1;
2330             //                  int kchrPtr = OS.GetScriptManagerVariable (cast(short) OS.smKCHRCache);
2331             //                  int key = -1;
2332             //                  int [] state = new int [1];
2333             //                  int [] encoding = new int [1];
2334             //                  short keyScript = cast(short) OS.GetScriptManagerVariable (cast(short) OS.smKeyScript);
2335             //                  short regionCode = cast(short) OS.GetScriptManagerVariable (cast(short) OS.smRegionCode);
2336             //                  if (OS.UpgradeScriptInfoToTextEncoding (keyScript, cast(short) OS.kTextLanguageDontCare, regionCode, null, encoding) is OS.paramErr) {
2337             //                      if (OS.UpgradeScriptInfoToTextEncoding (keyScript, cast(short) OS.kTextLanguageDontCare, cast(short) OS.kTextRegionDontCare, null, encoding) is OS.paramErr) {
2338             //                          encoding [0] = OS.kTextEncodingMacRoman;
2339             //                      }
2340             //                  }
2341             //                  int [] encodingInfo = new int [1];
2342             //                  OS.CreateUnicodeToTextInfoByEncoding (encoding [0], encodingInfo);
2343             //                  if (encodingInfo [0] !is 0) {
2344             //                      char [] input = {event.character};
2345             //                      byte [] buffer = new byte [2];
2346             //                      OS.ConvertFromUnicodeToPString (encodingInfo [0], 2, input, buffer);
2347             //                      OS.DisposeUnicodeToTextInfo (encodingInfo);
2348             //                      key = buffer [1] & 0x7f;
2349             //                  }
2350             //                  if (key is -1) return false;               
2351             //                  for (int i = 0 ; i <= 0x7F ; i++) {
2352             //                      int result1 = OS.KeyTranslate (kchrPtr, cast(short) (i | 512), state);
2353             //                      int result2 = OS.KeyTranslate (kchrPtr, cast(short) i, state);
2354             //                      if ((result1 & 0x7f) is key || (result2 & 0x7f) is key) {
2355             //                          vKey = i;
2356             //                          break;
2357             //                      }
2358             //                  }
2359             //                  if (vKey is -1) return false;
2360             //                  return OS.CGPostKeyboardEvent (key, vKey, type is DWT.KeyDown) is 0;
2361             //              }
2362             //          }
2363             //          case DWT.MouseDown:
2364             //          case DWT.MouseMove:
2365             //          case DWT.MouseUp: {
2366             //              CGPoint mouseCursorPosition = new CGPoint ();
2367             //              int chord = OS.GetCurrentEventButtonState ();
2368             //              if (type is DWT.MouseMove) {
2369             //                  mouseCursorPosition.x = event.x;
2370             //                  mouseCursorPosition.y = event.y;
2371             //                  return OS.CGPostMouseEvent (mouseCursorPosition, true, 5, (chord & 0x1) !is 0, (chord & 0x2) !is 0, (chord & 0x4) !is 0, (chord & 0x8) !is 0, (chord & 0x10) !is 0) is 0;
2372             //              } else {
2373             //                  int button = event.button;
2374             //                  if (button < 1 || button > 5) return false;
2375             //                  bool button1 = false, button2 = false, button3 = false, button4 = false, button5 = false;
2376             //                  switch (button) {
2377             //                      case 1: {
2378             //                          button1 = type is DWT.MouseDown;
2379             //                          button2 = (chord & 0x4) !is 0;
2380             //                          button3 = (chord & 0x2) !is 0;
2381             //                          button4 = (chord & 0x8) !is 0;
2382             //                          button5 = (chord & 0x10) !is 0;
2383             //                          break;
2384             //                      }
2385             //                      case 2: {
2386             //                          button1 = (chord & 0x1) !is 0;
2387             //                          button2 = type is DWT.MouseDown;
2388             //                          button3 = (chord & 0x2) !is 0;
2389             //                          button4 = (chord & 0x8) !is 0;
2390             //                          button5 = (chord & 0x10) !is 0;
2391             //                          break;
2392             //                      }
2393             //                      case 3: {
2394             //                          button1 = (chord & 0x1) !is 0;
2395             //                          button2 = (chord & 0x4) !is 0;
2396             //                          button3 = type is DWT.MouseDown;
2397             //                          button4 = (chord & 0x8) !is 0;
2398             //                          button5 = (chord & 0x10) !is 0;
2399             //                          break;
2400             //                      }
2401             //                      case 4: {
2402             //                          button1 = (chord & 0x1) !is 0;
2403             //                          button2 = (chord & 0x4) !is 0;
2404             //                          button3 = (chord & 0x2) !is 0;
2405             //                          button4 = type is DWT.MouseDown;
2406             //                          button5 = (chord & 0x10) !is 0;
2407             //                          break;
2408             //                      }
2409             //                      case 5: {
2410             //                          button1 = (chord & 0x1) !is 0;
2411             //                          button2 = (chord & 0x4) !is 0;
2412             //                          button3 = (chord & 0x2) !is 0;
2413             //                          button4 = (chord & 0x8) !is 0;
2414             //                          button5 = type is DWT.MouseDown;
2415             //                          break;
2416             //                      }
2417             //                  }
2418             //                  dwt.internal.carbon.Point pt = new dwt.internal.carbon.Point ();
2419             //                  OS.GetGlobalMouse (pt);
2420             //                  mouseCursorPosition.x = pt.h;
2421             //                  mouseCursorPosition.y = pt.v;
2422             //                  return OS.CGPostMouseEvent (mouseCursorPosition, true, 5, button1, button3, button2, button4, button5) is 0;
2423             //              }
2424             //          }
2425             //          case DWT.MouseWheel: {
2426             //              return OS.CGPostScrollWheelEvent (1, event.count) is 0;
2427             //          }
2428             //      }
2429             return false;
2430         }
2431     }
2432    
2433     void postEvent (Event event) {
2434         /*
2435          * Place the event at the end of the event queue.
2436          * This code is always called in the Display's
2437          * thread so it must be re-enterant but does not
2438          * need to be synchronized.
2439          */
2440         if (eventQueue is null) eventQueue = new Event [4];
2441         int index = 0;
2442         int length = eventQueue.length;
2443         while (index < length) {
2444             if (eventQueue [index] is null) break;
2445             index++;
2446         }
2447         if (index is length) {
2448             Event [] newQueue = new Event [length + 4];
2449             System.arraycopy (eventQueue, 0, newQueue, 0, length);
2450             eventQueue = newQueue;
2451         }
2452         eventQueue [index] = event;
2453     }
2454    
2455     /**
2456      * Maps a point from one coordinate system to another.
2457      * When the control is null, coordinates are mapped to
2458      * the display.
2459      * <p>
2460      * NOTE: On right-to-left platforms where the coordinate
2461      * systems are mirrored, special care needs to be taken
2462      * when mapping coordinates from one control to another
2463      * to ensure the result is correctly mirrored.
2464      *
2465      * Mapping a point that is the origin of a rectangle and
2466      * then adding the width and height is not equivalent to
2467      * mapping the rectangle.  When one control is mirrored
2468      * and the other is not, adding the width and height to a
2469      * point that was mapped causes the rectangle to extend
2470      * in the wrong direction.  Mapping the entire rectangle
2471      * instead of just one point causes both the origin and
2472      * the corner of the rectangle to be mapped.
2473      * </p>
2474      *
2475      * @param from the source <code>Control</code> or <code>null</code>
2476      * @param to the destination <code>Control</code> or <code>null</code>
2477      * @param point to be mapped
2478      * @return point with mapped coordinates
2479      *
2480      * @exception IllegalArgumentException <ul>
2481      *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
2482      *    <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
2483      * </ul>
2484      * @exception DWTException <ul>
2485      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2486      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2487      * </ul>
2488      *
2489      * @since 2.1.2
2490      */
2491     public Point map (Control from, Control to, Point point) {
2492         checkDevice ();
2493         if (point is null) error (DWT.ERROR_NULL_ARGUMENT);
2494         return map (from, to, point.x, point.y);
2495     }
2496    
2497     /**
2498      * Maps a point from one coordinate system to another.
2499      * When the control is null, coordinates are mapped to
2500      * the display.
2501      * <p>
2502      * NOTE: On right-to-left platforms where the coordinate
2503      * systems are mirrored, special care needs to be taken
2504      * when mapping coordinates from one control to another
2505      * to ensure the result is correctly mirrored.
2506      *
2507      * Mapping a point that is the origin of a rectangle and
2508      * then adding the width and height is not equivalent to
2509      * mapping the rectangle.  When one control is mirrored
2510      * and the other is not, adding the width and height to a
2511      * point that was mapped causes the rectangle to extend
2512      * in the wrong direction.  Mapping the entire rectangle
2513      * instead of just one point causes both the origin and
2514      * the corner of the rectangle to be mapped.
2515      * </p>
2516      *
2517      * @param from the source <code>Control</code> or <code>null</code>
2518      * @param to the destination <code>Control</code> or <code>null</code>
2519      * @param x coordinates to be mapped
2520      * @param y coordinates to be mapped
2521      * @return point with mapped coordinates
2522      *
2523      * @exception IllegalArgumentException <ul>
2524      *    <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
2525      * </ul>
2526      * @exception DWTException <ul>
2527      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2528      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2529      * </ul>
2530      *
2531      * @since 2.1.2
2532      */
2533     public Point map (Control from, Control to, int x, int y) {
2534         checkDevice ();
2535         if (from !is null && from.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT);
2536         if (to !is null && to.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT);
2537         Point point = new Point (x, y);
2538         if (from is to) return point;
2539         NSPoint pt = NSPoint();
2540         pt.x = x;
2541         pt.y = y;
2542         NSWindow fromWindow = from !is null ? from.view.window() : null;
2543         NSWindow toWindow = to !is null ? to.view.window() : null;
2544         if (toWindow !is null && fromWindow !is null && toWindow.id is fromWindow.id) {
2545             pt = from.view.convertPoint_toView_(pt, to.view);
2546         } else {
2547             NSRect primaryFrame = getPrimaryFrame();
2548             if (from !is null) {
2549                 NSView view = from.contentView ();
2550                 pt = view.convertPoint_toView_(pt, null);
2551                 pt = fromWindow.convertBaseToScreen(pt);
2552                 pt.y = primaryFrame.height - pt.y;
2553             }
2554             if (to !is null) {
2555                 NSView view = to.contentView ();
2556                 pt.y = primaryFrame.height - pt.y;
2557                 pt = toWindow.convertScreenToBase(pt);
2558                 pt = view.convertPoint_fromView_(pt, null);
2559             }
2560         }
2561         point.x = cast(int)pt.x;
2562         point.y = cast(int)pt.y;
2563         return point;
2564     }
2565    
2566     /**
2567      * Maps a point from one coordinate system to another.
2568      * When the control is null, coordinates are mapped to
2569      * the display.
2570      * <p>
2571      * NOTE: On right-to-left platforms where the coordinate
2572      * systems are mirrored, special care needs to be taken
2573      * when mapping coordinates from one control to another
2574      * to ensure the result is correctly mirrored.
2575      *
2576      * Mapping a point that is the origin of a rectangle and
2577      * then adding the width and height is not equivalent to
2578      * mapping the rectangle.  When one control is mirrored
2579      * and the other is not, adding the width and height to a
2580      * point that was mapped causes the rectangle to extend
2581      * in the wrong direction.  Mapping the entire rectangle
2582      * instead of just one point causes both the origin and
2583      * the corner of the rectangle to be mapped.
2584      * </p>
2585      *
2586      * @param from the source <code>Control</code> or <code>null</code>
2587      * @param to the destination <code>Control</code> or <code>null</code>
2588      * @param rectangle to be mapped
2589      * @return rectangle with mapped coordinates
2590      *
2591      * @exception IllegalArgumentException <ul>
2592      *    <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
2593      *    <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
2594      * </ul>
2595      * @exception DWTException <ul>
2596      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2597      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2598      * </ul>
2599      *
2600      * @since 2.1.2
2601      */
2602     public Rectangle map (Control from, Control to, Rectangle rectangle) {
2603         checkDevice ();
2604         if (rectangle is null) error (DWT.ERROR_NULL_ARGUMENT);
2605         return map (from, to, rectangle.x, rectangle.y, rectangle.width, rectangle.height);
2606     }
2607    
2608     /**
2609      * Maps a point from one coordinate system to another.
2610      * When the control is null, coordinates are mapped to
2611      * the display.
2612      * <p>
2613      * NOTE: On right-to-left platforms where the coordinate
2614      * systems are mirrored, special care needs to be taken
2615      * when mapping coordinates from one control to another
2616      * to ensure the result is correctly mirrored.
2617      *
2618      * Mapping a point that is the origin of a rectangle and
2619      * then adding the width and height is not equivalent to
2620      * mapping the rectangle.  When one control is mirrored
2621      * and the other is not, adding the width and height to a
2622      * point that was mapped causes the rectangle to extend
2623      * in the wrong direction.  Mapping the entire rectangle
2624      * instead of just one point causes both the origin and
2625      * the corner of the rectangle to be mapped.
2626      * </p>
2627      *
2628      * @param from the source <code>Control</code> or <code>null</code>
2629      * @param to the destination <code>Control</code> or <code>null</code>
2630      * @param x coordinates to be mapped
2631      * @param y coordinates to be mapped
2632      * @param width coordinates to be mapped
2633      * @param height coordinates to be mapped
2634      * @return rectangle with mapped coordinates
2635      *
2636      * @exception IllegalArgumentException <ul>
2637      *    <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
2638      * </ul>
2639      * @exception DWTException <ul>
2640      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2641      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2642      * </ul>
2643      *
2644      * @since 2.1.2
2645      */
2646     public Rectangle map (Control from, Control to, int x, int y, int width, int height) {
2647         checkDevice ();
2648         if (from !is null && from.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT);
2649         if (to !is null && to.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT);
2650         Rectangle rectangle = new Rectangle (x, y, width, height);
2651         if (from is to) return rectangle;
2652         NSPoint pt = NSPoint();
2653         pt.x = x;
2654         pt.y = y;
2655         NSWindow fromWindow = from !is null ? from.view.window() : null;
2656         NSWindow toWindow = to !is null ? to.view.window() : null;
2657         if (toWindow !is null && fromWindow !is null && toWindow.id is fromWindow.id) {
2658             pt = from.view.convertPoint_toView_(pt, to.view);
2659         } else {
2660             NSRect primaryFrame = getPrimaryFrame();
2661             if (from !is null) {
2662                 NSView view = from.contentView ();
2663                 pt = view.convertPoint_toView_(pt, null);
2664                 pt = fromWindow.convertBaseToScreen(pt);
2665                 pt.y = primaryFrame.height - pt.y;
2666             }
2667             if (to !is null) {
2668                 NSView view = to.contentView ();
2669                 pt.y = primaryFrame.height - pt.y;
2670                 pt = toWindow.convertScreenToBase(pt);
2671                 pt = view.convertPoint_fromView_(pt, null);
2672             }
2673         }
2674         rectangle.x = cast(int)pt.x;
2675         rectangle.y = cast(int)pt.y;
2676         return rectangle;
2677     }
2678    
2679     /**
2680      * Reads an event from the operating system's event queue,
2681      * dispatches it appropriately, and returns <code>true</code>
2682      * if there is potentially more work to do, or <code>false</code>
2683      * if the caller can sleep until another event is placed on
2684      * the event queue.
2685      * <p>
2686      * In addition to checking the system event queue, this method also
2687      * checks if any inter-thread messages (created by <code>syncExec()</code>
2688      * or <code>asyncExec()</code>) are waiting to be processed, and if
2689      * so handles them before returning.
2690      * </p>
2691      *
2692      * @return <code>false</code> if the caller can sleep upon return from this method
2693      *
2694      * @exception DWTException <ul>
2695      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2696      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2697      *    <li>ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message</li>
2698      * </ul>
2699      *
2700      * @see #sleep
2701      * @see #wake
2702      */
2703     public bool readAndDispatch () {
2704         checkDevice ();
2705         if (loopCounter is 0) {
2706             pool.release();
2707             pool = cast(NSAutoreleasePool)(new NSAutoreleasePool()).alloc().init();
2708         }
2709         loopCounter ++;
2710         bool events = false;
2711         events |= runTimers ();
2712         events |= runContexts ();
2713         events |= runPopups ();
2714         NSEvent event = application.nextEventMatchingMask(0, null, OS.NSDefaultRunLoopMode, true);
2715        
2716         try {
2717         if (event !is null) {
2718             events = true;
2719             application.sendEvent(event);
2720         }
2721             //      NSEvent event = NSEvent.otherEventWithType(OS.NSApplicationDefined, NSPoint(), 0, 0, 0, null, SWT_IDLE_TYPE, 0, 0);
2722             //      application.postEvent(event, false);
2723             //      idle = true;
2724             //      application.run();
2725             //      events |= !idle;
2726             if (events) {
2727                 runDeferredEvents ();
2728                 return true;
2729             }
2730             return runAsyncMessages (false);
2731         } finally {
2732             loopCounter --;
2733         }
2734        
2735     }
2736    
2737     static void register (Display display) {
2738         synchronized (Device.classinfo) {
2739             for (int i=0; i<Displays.length; i++) {
2740                 if (Displays [i] is null) {
2741                     Displays [i] = display;
2742                     return;
2743                 }
2744             }
2745             Display [] newDisplays = new Display [Displays.length + 4];
2746             System.arraycopy (Displays, 0, newDisplays, 0, Displays.length);
2747             newDisplays [Displays.length] = display;
2748             Displays = newDisplays;
2749         }
2750     }
2751    
2752     /**
2753      * Releases any internal resources back to the operating
2754      * system and clears all fields except the device handle.
2755      * <p>
2756      * Disposes all shells which are currently open on the display.
2757      * After this method has been invoked, all related related shells
2758      * will answer <code>true</code> when sent the message
2759      * <code>isDisposed()</code>.
2760      * </p><p>
2761      * When a device is destroyed, resources that were acquired
2762      * on behalf of the programmer need to be returned to the
2763      * operating system.  For example, if the device allocated a
2764      * font to be used as the system font, this font would be
2765      * freed in <code>release</code>.  Also,to assist the garbage
2766      * collector and minimize the amount of memory that is not
2767      * reclaimed when the programmer keeps a reference to a
2768      * disposed device, all fields except the handle are zero'd.
2769      * The handle is needed by <code>destroy</code>.
2770      * </p>
2771      * This method is called before <code>destroy</code>.
2772      *
2773      * @see Device#dispose
2774      * @see #destroy
2775      */
2776     protected void release () {
2777         disposing = true;
2778         sendEvent (DWT.Dispose, new Event ());
2779         Shell [] shells = getShells ();
2780         for (int i=0; i<shells.length; i++) {
2781             Shell shell = shells [i];
2782             if (!shell.isDisposed ()) shell.dispose ();
2783         }
2784         if (tray !is null) tray.dispose ();
2785         tray = null;
2786         while (readAndDispatch ()) {}
2787         if (disposeList !is null) {
2788             for (int i=0; i<disposeList.length; i++) {
2789                 if (disposeList [i] !is null) disposeList [i].run ();
2790             }
2791         }
2792         disposeList = null;
2793         synchronizer.releaseSynchronizer ();
2794         synchronizer = null;
2795         releaseDisplay ();
2796         super.release ();
2797     }
2798    
2799     void releaseDisplay () {   
2800         /* Release the System Images */
2801         if (errorImage !is null) errorImage.dispose ();
2802         if (infoImage !is null) infoImage.dispose ();
2803         if (warningImage !is null) warningImage.dispose ();
2804         errorImage = infoImage = warningImage = null;
2805        
2806         currentCaret = null;
2807        
2808         /* Release Timers */
2809         if (hoverTimer !is null) timerExec(-1, hoverTimer);
2810         hoverTimer = null;
2811         if (caretTimer !is null) timerExec(-1, caretTimer);
2812         caretTimer = null;
2813         if (nsTimers !is null) {
2814             for (int i=0; i<nsTimers.length; i++) {
2815                 if (nsTimers [i] !is null) {
2816                     nsTimers [i].invalidate();
2817                     nsTimers [i].release();
2818                 }
2819             }
2820         }
2821         nsTimers = null;
2822         if (timerDelegate !is null) timerDelegate.release();
2823         timerDelegate = null;
2824        
2825         /* Release the System Cursors */
2826         for (int i = 0; i < cursors.length; i++) {
2827             if (cursors [i] !is null) cursors [i].dispose ();
2828         }
2829         cursors = null;
2830        
2831         /* Release Dock image */
2832         if (dockImage !is null) dockImage.release();
2833         dockImage = null;
2834        
2835         if (screenWindow !is null) screenWindow.release();
2836         screenWindow = null;
2837        
2838         modalShells = null;
2839         menuBar = null;
2840         menus = null;
2841        
2842         if (markedAttributes !is null) markedAttributes.release();
2843         markedAttributes = null;
2844        
2845         /* The release pool needs to be released before the call backs. */
2846         if (pool !is null) pool.release();
2847         pool = null;
2848        
2849         if (application !is null && applicationClass !is null) {
2850             OS.object_setClass (application.id, applicationClass);
2851         }
2852         application = null;
2853         applicationClass = null;
2854     }
2855    
2856     void removeContext (NSGraphicsContext context) {
2857         if (contexts is null) return;
2858         int count = 0;
2859         for (int i = 0; i < contexts.length; i++) {
2860             if (contexts[i] !is null) {
2861                 if (contexts [i].id is context.id) {
2862                     contexts[i] = null;
2863                 } else {
2864                     count++;
2865                 }
2866             }
2867         }
2868         if (count is 0) contexts = null;
2869     }
2870    
2871     /**
2872      * Removes the listener from the collection of listeners who will
2873      * be notified when an event of the given type occurs anywhere in
2874      * a widget. The event type is one of the event constants defined
2875      * in class <code>DWT</code>.
2876      *
2877      * @param eventType the type of event to listen for
2878      * @param listener the listener which should no longer be notified when the event occurs
2879      *
2880      * @exception IllegalArgumentException <ul>
2881      *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2882      * </ul>
2883      * @exception DWTException <ul>
2884      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2885      * </ul>
2886      *
2887      * @see Listener
2888      * @see DWT
2889      * @see #addFilter
2890      * @see #addListener
2891      *
2892      * @since 3.0
2893      */
2894     public void removeFilter (int eventType, Listener listener) {
2895         checkDevice ();
2896         if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
2897         if (filterTable is null) return;
2898         filterTable.unhook (eventType, listener);
2899         if (filterTable.size () is 0) filterTable = null;
2900     }
2901    
2902     /**
2903      * Removes the listener from the collection of listeners who will
2904      * be notified when an event of the given type occurs. The event type
2905      * is one of the event constants defined in class <code>DWT</code>.
2906      *
2907      * @param eventType the type of event to listen for
2908      * @param listener the listener which should no longer be notified
2909      *
2910      * @exception IllegalArgumentException <ul>
2911      *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
2912      * </ul>
2913      * @exception DWTException <ul>
2914      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2915      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
2916      * </ul>
2917      *
2918      * @see Listener
2919      * @see DWT
2920      * @see #addListener
2921      *
2922      * @since 2.0
2923      */
2924     public void removeListener (int eventType, Listener listener) {
2925         checkDevice ();
2926         if (listener is null) error (DWT.ERROR_NULL_ARGUMENT);
2927         if (eventTable is null) return;
2928         eventTable.unhook (eventType, listener);
2929     }
2930    
2931     Widget removeWidget (NSObject view) {
2932         if (view is null) return null;
2933         void* jniRef;
2934         OS.object_getInstanceVariable(view.id, SWT_OBJECT, jniRef);
2935         if (jniRef is null) return null;
2936         Widget widget = cast(Widget)OS.JNIGetObject(jniRef);
2937         OS.object_setInstanceVariable(view.id, SWT_OBJECT, null);
2938         return widget;
2939     }
2940    
2941     void removeMenu (Menu menu) {
2942         if (menus is null) return;
2943         for (int i = 0; i < menus.length; i++) {
2944             if (menus [i] is menu) {
2945                 menus[i] = null;
2946                 break;
2947             }
2948         }
2949     }
2950    
2951     void removePopup (Menu menu) {
2952         if (popups is null) return;
2953         for (int i=0; i<popups.length; i++) {
2954             if (popups [i] is menu) {
2955                 popups [i] = null;
2956                 return;
2957             }
2958         }
2959     }
2960    
2961     bool runAsyncMessages (bool all) {
2962         return synchronizer.runAsyncMessages (all);
2963     }
2964    
2965     bool runContexts () {
2966         if (contexts !is null) {
2967             for (int i = 0; i < contexts.length; i++) {
2968                 if (contexts[i] !is null) contexts[i].flushGraphics();
2969             }
2970         }
2971         return false;
2972     }
2973    
2974     bool runDeferredEvents () {
2975         /*
2976          * Run deferred events.  This code is always
2977          * called  in the Display's thread so it must
2978          * be re-enterant need not be synchronized.
2979          */
2980         while (eventQueue !is null) {
2981            
2982             /* Take an event off the queue */
2983             Event event = eventQueue [0];
2984             if (event is null) break;
2985             int length_ = eventQueue.length;
2986             System.arraycopy (eventQueue, 1, eventQueue, 0, --length_);
2987             eventQueue [length_] = null;
2988            
2989             /* Run the event */
2990             Widget widget = event.widget;
2991             if (widget !is null && !widget.isDisposed ()) {
2992                 Widget item = event.item;
2993                 if (item is null || !item.isDisposed ()) {
2994                     widget.notifyListeners (event.type, event);
2995                 }
2996             }
2997            
2998             /*
2999              * At this point, the event queue could
3000              * be null due to a recursive invokation
3001              * when running the event.
3002              */
3003         }
3004        
3005         /* Clear the queue */
3006         eventQueue = null;
3007         return true;
3008     }
3009    
3010     bool runPopups () {
3011         if (popups is null) return false;
3012         bool result = false;
3013         while (popups !is null) {
3014             Menu menu = popups [0];
3015             if (menu is null) break;
3016             int length_ = popups.length;
3017             System.arraycopy (popups, 1, popups, 0, --length_);
3018             popups [length_] = null;
3019             //      clearMenuFlags ();
3020             runDeferredEvents ();
3021             if (!menu.isDisposed ()) menu._setVisible (true);
3022             //      clearMenuFlags ();
3023             result = true;
3024         }
3025         popups = null;
3026         return result;
3027     }
3028    
3029     bool runTimers () {
3030         if (timerList is null) return false;
3031         bool result = false;
3032         for (int i=0; i<timerList.length; i++) {
3033             if (nsTimers [i] is null && timerList [i] !is null) {
3034                 Runnable runnable = timerList [i];
3035                 timerList [i] = null;
3036                 if (runnable !is null) {
3037                     result = true;
3038                     runnable.run ();
3039                 }
3040             }
3041         }
3042         return result;
3043     }
3044    
3045     void sendEvent (int eventType, Event event) {
3046         if (eventTable is null && filterTable is null) {
3047             return;
3048         }
3049         if (event is null) event = new Event ();
3050         event.display = this;
3051         event.type = eventType;
3052         if (event.time is 0) event.time = getLastEventTime ();
3053         if (!filterEvent (event)) {
3054             if (eventTable !is null) eventTable.sendEvent (event);
3055         }
3056     }
3057    
3058     /**
3059      * On platforms which support it, sets the application name
3060      * to be the argument. On Motif, for example, this can be used
3061      * to set the name used for resource lookup.  Specifying
3062      * <code>null</code> for the name clears it.
3063      *
3064      * @param name the new app name or <code>null</code>
3065      */
3066     public static void setAppName (String name) {
3067         APP_NAME = name;
3068     }
3069    
3070     //TODO use custom timer instead of timerExec
3071     Runnable hoverTimer;
3072
3073     class HoverTimer : Runnable
3074     {
3075         public void run () {
3076             if (currentControl !is null && !currentControl.isDisposed()) {
3077                 currentControl.sendMouseEvent (null, DWT.MouseHover, trackingControl !is null);
3078             }
3079         }
3080     }
3081    
3082     //TODO - use custom timer instead of timerExec
3083     Runnable caretTimer;
3084
3085     class CaretTimer : Runnable
3086     {
3087         public void run () {
3088             if (currentCaret !is null) {
3089                 if (this.outer.currentCaret is null || this.outer.currentCaret.isDisposed()) return;
3090                 if (currentCaret.blinkCaret ()) {
3091                     int blinkRate = currentCaret.blinkRate;
3092                     if (blinkRate !is 0) timerExec (blinkRate, this);
3093                 } else {
3094                     currentCaret = null;
3095                 }
3096             }
3097         }
3098     }
3099    
3100     void setCurrentCaret (Caret caret) {
3101         //  if (caretID !is 0) OS.RemoveEventLoopTimer (caretID);
3102         //  caretID = 0;
3103         currentCaret = caret;       
3104         if (currentCaret !is null) {
3105             int blinkRate = currentCaret.blinkRate;
3106             timerExec (blinkRate, caretTimer);
3107         }
3108     }
3109    
3110     void setCursor (Control control) {
3111         Cursor cursor = null;
3112         if (control !is null) cursor = control.findCursor ();
3113         if (cursor is null) cursor = getSystemCursor (DWT.CURSOR_ARROW);
3114         cursor.handle.set ();
3115     }
3116    
3117     /**
3118      * Sets the location of the on-screen pointer relative to the top left corner
3119      * of the screen.  <b>Note: It is typically considered bad practice for a
3120      * program to move the on-screen pointer location.</b>
3121      *
3122      * @param x the new x coordinate for the cursor
3123      * @param y the new y coordinate for the cursor
3124      *
3125      * @exception DWTException <ul>
3126      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3127      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3128      * </ul>
3129      *
3130      * @since 2.1
3131      */
3132     public void setCursorLocation (int x, int y) {
3133         checkDevice ();
3134         CGPoint pt = CGPoint ();
3135         pt.x = x;  pt.y = y;
3136         OS.CGWarpMouseCursorPosition (pt);
3137     }
3138    
3139     /**
3140      * Sets the location of the on-screen pointer relative to the top left corner
3141      * of the screen.  <b>Note: It is typically considered bad practice for a
3142      * program to move the on-screen pointer location.</b>
3143      *
3144      * @param point new position
3145      *
3146      * @exception DWTException <ul>
3147      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3148      *    <li>ERROR_NULL_ARGUMENT - if the point is null
3149      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3150      * </ul>
3151      *
3152      * @since 2.0
3153      */
3154     public void setCursorLocation (Point point) {
3155         checkDevice ();
3156         if (point is null) error (DWT.ERROR_NULL_ARGUMENT);
3157         setCursorLocation (point.x, point.y);
3158     }
3159    
3160     /**
3161      * Sets the application defined property of the receiver
3162      * with the specified name to the given argument.
3163      * <p>
3164      * Applications may have associated arbitrary objects with the
3165      * receiver in this fashion. If the objects stored in the
3166      * properties need to be notified when the display is disposed
3167      * of, it is the application's responsibility provide a
3168      * <code>disposeExec()</code> handler which does so.
3169      * </p>
3170      *
3171      * @param key the name of the property
3172      * @param value the new value for the property
3173      *
3174      * @exception IllegalArgumentException <ul>
3175      *    <li>ERROR_NULL_ARGUMENT - if the key is null</li>
3176      * </ul>
3177      * @exception DWTException <ul>
3178      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3179      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3180      * </ul>
3181      *
3182      * @see #getData(String)
3183      * @see #disposeExec(Runnable)
3184      */
3185     public void setData (String key, Object value) {
3186         checkDevice ();
3187         //if (key is null) error (DWT.ERROR_NULL_ARGUMENT);   
3188        
3189         if (key.equals (ADD_WIDGET_KEY)) {
3190             auto wrap = cast(ArrayWrapperObject) value;
3191            
3192             if (wrap is null)
3193                 DWT.error(DWT.ERROR_INVALID_ARGUMENT, null, " []");
3194            
3195             Object [] data = wrap.array;
3196             NSObject object = cast(NSObject)data [0];
3197             Widget widget = cast(Widget)data [1];
3198             if (widget is null) {
3199                 removeWidget (object);
3200             } else {
3201                 addWidget (object, widget);
3202             }
3203         }
3204        
3205         /* Remove the key/value pair */
3206         if (value is null) {
3207             if (keys is null) return;
3208             int index = 0;
3209             while (index < keys.length && !keys [index].equals (key)) index++;
3210             if (index is keys.length) return;
3211             if (keys.length is 1) {
3212                 keys = null;
3213                 values = null;
3214             } else {
3215                 String [] newKeys = new String [keys.length - 1];
3216                 Object [] newValues = new Object [values.length - 1];
3217                 System.arraycopy (keys, 0, newKeys, 0, index);
3218                 System.arraycopy (keys, index + 1, newKeys, index, newKeys.length - index);
3219                 System.arraycopy (values, 0, newValues, 0, index);
3220                 System.arraycopy (values, index + 1, newValues, index, newValues.length - index);
3221                 keys = newKeys;
3222                 values = newValues;
3223             }
3224             return;
3225         }
3226        
3227         /* Add the key/value pair */
3228         if (keys is null) {
3229             keys = [key];
3230             values = [value];
3231             return;
3232         }
3233         for (int i=0; i<keys.length; i++) {
3234             if (keys [i].equals (key)) {
3235                 values [i] = value;
3236                 return;
3237             }
3238         }
3239         String [] newKeys = new String [keys.length + 1];
3240         Object [] newValues = new Object [values.length + 1];
3241         System.arraycopy (keys, 0, newKeys, 0, keys.length);
3242         System.arraycopy (values, 0, newValues, 0, values.length);
3243         newKeys [keys.length] = key;
3244         newValues [values.length] = value;
3245         keys = newKeys;
3246         values = newValues;
3247     }
3248    
3249     void setMenuBar (Menu menu) {
3250         if (menu is menuBar) return;
3251         menuBar = menu;
3252         //remove all existing menu items except the application menu
3253         NSMenu menubar = application.mainMenu();
3254         NSInteger count = menubar.numberOfItems();
3255         while (count > 1) {
3256             menubar.removeItemAtIndex(count - 1);
3257             count--;
3258         }
3259         //set parent of each item to NULL and add them to menubar
3260         if (menu !is null) {
3261             MenuItem[] items = menu.getItems();
3262             for (int i = 0; i < items.length; i++) {
3263                 items[i].nsItem.setMenu(null);
3264                 menubar.addItem(items[i].nsItem);
3265             }
3266         }
3267     }
3268    
3269     void setModalShell (Shell shell) {
3270         if (modalShells is null) modalShells = new Shell [4];
3271         int index = 0, length = modalShells.length;
3272         while (index < length) {
3273             if (modalShells [index] is shell) return;
3274             if (modalShells [index] is null) break;
3275             index++;
3276         }
3277         if (index is length) {
3278             Shell [] newModalShells = new Shell [length + 4];
3279             System.arraycopy (modalShells, 0, newModalShells, 0, length);
3280             modalShells = newModalShells;
3281         }
3282         modalShells [index] = shell;
3283         Shell [] shells = getShells ();
3284         for (int i=0; i<shells.length; i++) shells [i].updateModal ();
3285     }
3286    
3287     /**
3288      * Sets the application defined, display specific data
3289      * associated with the receiver, to the argument.
3290      * The <em>display specific data</em> is a single,
3291      * unnamed field that is stored with every display.
3292      * <p>
3293      * Applications may put arbitrary objects in this field. If
3294      * the object stored in the display specific data needs to
3295      * be notified when the display is disposed of, it is the
3296      * application's responsibility provide a
3297      * <code>disposeExec()</code> handler which does so.
3298      * </p>
3299      *
3300      * @param data the new display specific data
3301      *
3302      * @exception DWTException <ul>
3303      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3304      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3305      * </ul>
3306      *
3307      * @see #getData()
3308      * @see #disposeExec(Runnable)
3309      */
3310     public void setData (Object data) {
3311         checkDevice ();
3312         this.data = data;
3313     }
3314    
3315     /**
3316      * Sets the synchronizer used by the display to be
3317      * the argument, which can not be null.
3318      *
3319      * @param synchronizer the new synchronizer for the display (must not be null)
3320      *
3321      * @exception IllegalArgumentException <ul>
3322      *    <li>ERROR_NULL_ARGUMENT - if the synchronizer is null</li>
3323      * </ul>
3324      * @exception DWTException <ul>
3325      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3326      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3327      *    <li>ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message</li>
3328      * </ul>
3329      */
3330     public void setSynchronizer (Synchronizer synchronizer) {
3331         checkDevice ();
3332         if (synchronizer is null) error (DWT.ERROR_NULL_ARGUMENT);
3333         if (synchronizer is this.synchronizer) return;
3334         Synchronizer oldSynchronizer;
3335         synchronized (Device.classinfo) {
3336             oldSynchronizer = this.synchronizer;
3337             this.synchronizer = synchronizer;
3338         }
3339         if (oldSynchronizer !is null) {
3340             oldSynchronizer.runAsyncMessages(true);
3341         }
3342     }
3343    
3344     /**
3345      * Causes the user-interface thread to <em>sleep</em> (that is,
3346      * to be put in a state where it does not consume CPU cycles)
3347      * until an event is received or it is otherwise awakened.
3348      *
3349      * @return <code>true</code> if an event requiring dispatching was placed on the queue.
3350      *
3351      * @exception DWTException <ul>
3352      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3353      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3354      * </ul>
3355      *
3356      * @see #wake
3357      */
3358     public bool sleep () {
3359         checkDevice ();
3360         if (getMessageCount () !is 0) return true;
3361         if (loopCounter is 0) {
3362             pool.release();
3363             pool = cast(NSAutoreleasePool)(new NSAutoreleasePool()).alloc().init();
3364         }
3365         allowTimers = runAsyncMessages = false;
3366         NSRunLoop.currentRunLoop().runMode(OS.NSDefaultRunLoopMode, NSDate.distantFuture());
3367         allowTimers = runAsyncMessages = true;
3368         return true;
3369     }
3370    
3371     int sourceProc (int info) {
3372         return 0;
3373     }
3374    
3375     /**
3376      * Causes the <code>run()</code> method of the runnable to
3377      * be invoked by the user-interface thread at the next
3378      * reasonable opportunity. The thread which calls this method
3379      * is suspended until the runnable completes.  Specifying <code>null</code>
3380      * as the runnable simply wakes the user-interface thread.
3381      * <p>
3382      * Note that at the time the runnable is invoked, widgets
3383      * that have the receiver as their display may have been
3384      * disposed. Therefore, it is necessary to check for this
3385      * case inside the runnable before accessing the widget.
3386      * </p>
3387      *
3388      * @param runnable code to run on the user-interface thread or <code>null</code>
3389      *
3390      * @exception DWTException <ul>
3391      *    <li>ERROR_FAILED_EXEC - if an exception occurred when executing the runnable</li>
3392      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3393      * </ul>
3394      *
3395      * @see #asyncExec
3396      */
3397     public void syncExec (Runnable runnable) {
3398         Synchronizer synchronizer;
3399         synchronized (Device.classinfo) {
3400             if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
3401             synchronizer = this.synchronizer;
3402         }
3403         synchronizer.syncExec (runnable);
3404     }
3405    
3406     /**
3407      * Causes the <code>run()</code> method of the runnable to
3408      * be invoked by the user-interface thread after the specified
3409      * number of milliseconds have elapsed. If milliseconds is less
3410      * than zero, the runnable is not executed.
3411      * <p>
3412      * Note that at the time the runnable is invoked, widgets
3413      * that have the receiver as their display may have been
3414      * disposed. Therefore, it is necessary to check for this
3415      * case inside the runnable before accessing the widget.
3416      * </p>
3417      *
3418      * @param milliseconds the delay before running the runnable
3419      * @param runnable code to run on the user-interface thread
3420      *
3421      * @exception IllegalArgumentException <ul>
3422      *    <li>ERROR_NULL_ARGUMENT - if the runnable is null</li>
3423      * </ul>
3424      * @exception DWTException <ul>
3425      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3426      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3427      * </ul>
3428      *
3429      * @see #asyncExec
3430      */
3431     public void timerExec (int milliseconds, Runnable runnable) {
3432         checkDevice ();
3433         //TODO - remove a timer, reschedule a timer not tested
3434         if (runnable is null) error (DWT.ERROR_NULL_ARGUMENT);
3435         if (timerList is null) timerList = new Runnable [4];
3436         if (nsTimers is null) nsTimers = new NSTimer [4];
3437         int index = 0;
3438         while (index < timerList.length) {
3439             if (timerList [index] is runnable) break;
3440             index++;
3441         }
3442         if (index !is timerList.length) {
3443             NSTimer timer = nsTimers [index];
3444             if (timer is null) {
3445                 timerList [index] = null;
3446             } else {
3447                 if (milliseconds < 0) {
3448                     timer.invalidate();
3449                     timerList [index] = null;
3450                     nsTimers [index] = null;
3451                 } else {
3452                     timer.setFireDate(NSDate.dateWithTimeIntervalSinceNow (milliseconds / 1000.0));
3453                 }
3454                 return;
3455             }
3456         }
3457         if (milliseconds < 0) return;
3458         index = 0;
3459         while (index < timerList.length) {
3460             if (timerList [index] is null) break;
3461             index++;
3462         }
3463         if (index is timerList.length) {
3464             Runnable [] newTimerList = new Runnable [timerList.length + 4];
3465             SimpleType!(Runnable).arraycopy (timerList, 0, newTimerList, 0, timerList.length);
3466             timerList = newTimerList;
3467             NSTimer [] newTimerIds = new NSTimer [nsTimers.length + 4];
3468             System.arraycopy (nsTimers, 0, newTimerIds, 0, nsTimers.length);
3469             nsTimers = newTimerIds;
3470         }
3471         NSNumber userInfo = NSNumber.numberWithInt(index);
3472         NSTimer timer = NSTimer.scheduledTimerWithTimeInterval(milliseconds / 1000.0, timerDelegate, OS.sel_timerProc_, userInfo, false);
3473         timer.retain();
3474         if (timer !is null) {
3475             nsTimers [index] = timer;
3476             timerList [index] = runnable;
3477         }
3478     }
3479    
3480     objc.id timerProc (objc.id id, objc.SEL sel, objc.id timerID) {
3481         NSTimer timer = new NSTimer (timerID);
3482         NSNumber number = new NSNumber(timer.userInfo());
3483         int index = number.intValue();
3484         if (timerList is null) return null;
3485         if (0 <= index && index < timerList.length) {
3486             if (allowTimers) {
3487                 Runnable runnable = timerList [index];
3488                 timerList [index] = null;
3489                 nsTimers [index] = null;
3490                 if (runnable !is null) runnable.run ();
3491             } else {
3492                 nsTimers [index] = null;
3493                 wakeThread ();
3494             }
3495         }
3496         timer.release();
3497         return null;
3498     }
3499    
3500     /**
3501      * Forces all outstanding paint requests for the display
3502      * to be processed before this method returns.
3503      *
3504      * @exception DWTException <ul>
3505      *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
3506      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3507      * </ul>
3508      *
3509      * @see Control#update()
3510      */
3511     public void update () {
3512         checkDevice ();
3513         //  Shell [] shells = getShells ();
3514         //  for (int i=0; i<shells.length; i++) {
3515         //      Shell shell = shells [i];
3516         //      if (!shell.isDisposed ()) shell.update (true);
3517         //  }
3518        
3519     }
3520    
3521     /**
3522      * If the receiver's user-interface thread was <code>sleep</code>ing,
3523      * causes it to be awakened and start running again. Note that this
3524      * method may be called from any thread.
3525      *
3526      * @exception DWTException <ul>
3527      *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
3528      * </ul>
3529      *
3530      * @see #sleep
3531      */
3532     public void wake () {
3533         synchronized (Device.classinfo) {
3534             if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
3535             if (thread is Thread.getThis ()) return;
3536             wakeThread ();
3537         }
3538     }
3539    
3540     void wakeThread () {
3541         NSObject object = (new NSObject()).alloc().init();
3542         object.performSelectorOnMainThread(OS.sel_release, null, false);
3543     }
3544    
3545     Control findControl (NSEvent nsEvent, bool checkGrab, bool checkTrim, bool checkWindows) {
3546         if (checkGrab && grabControl !is null && !grabControl.isDisposed()) return grabControl;
3547         NSPoint point = NSEvent.mouseLocation();
3548         NSView view = null;
3549         NSWindow window = nsEvent !is null ? nsEvent.window() : null;
3550         if (window !is null) {
3551             view = window.contentView().hitTest (window.convertScreenToBase(point));
3552         }
3553         if (view is null && checkWindows) {
3554             NSArray windows = application.orderedWindows();
3555             for (int i = 0; i < windows.count() && view is null; i++) {
3556                 window = new NSWindow(windows.objectAtIndex(i));
3557                 NSView contentView = window.contentView();
3558                 if (contentView !is null) view = contentView.hitTest (window.convertScreenToBase(point));
3559             }
3560         }
3561         Control control = null;
3562         if (view !is null) {
3563             do {auto vi = view.id;
3564                 Widget widget = getWidget (view);
3565                 if (cast(Control) widget) {
3566                     control = cast(Control)widget;
3567                     break;
3568                 }
3569                 view = view.superview();
3570             } while (view !is null);
3571         }
3572         if (checkTrim) {
3573             if (control !is null && control.isTrim (view)) control = null;
3574         }
3575         return control;
3576     }
3577    
3578     objc.id applicationNextEventMatchingMask (objc.id id, objc.SEL sel, objc.id mask, objc.id expiration, objc.id mode, objc.id dequeue) {
3579         objc_super super_struct = objc_super();
3580         super_struct.receiver = id;
3581         super_struct.super_class = cast(objc.Class) OS.objc_msgSend(id, OS.sel_superclass);
3582         objc.id result = OS.objc_msgSendSuper(&super_struct, sel, mask, expiration, mode, dequeue !is null);
3583         if (result !is null) {
3584             if (trackingControl !is null && dequeue !is null) {
3585                 NSEvent nsEvent = new NSEvent(result);
3586                 applicationSendMouseEvent(nsEvent, true);
3587             }
3588         }
3589         return result;
3590     }
3591    
3592     void applicationSendMouseEvent (NSEvent nsEvent, bool send) {
3593         if (send) runDeferredEvents();
3594         bool up = false;
3595         NSEventType type = nsEvent.type();
3596         switch (type) {
3597             case OS.NSLeftMouseDown:
3598             case OS.NSRightMouseDown:
3599             case OS.NSOtherMouseDown: {
3600                 Control control = grabControl = findControl(nsEvent, false, true, false);
3601                 if (control !is null) {
3602                     if (nsEvent.clickCount() is 1 && (control.state & Widget.DRAG_DETECT) !is 0 && control.hooks (DWT.DragDetect) && control.dragDetect()) {
3603                         dragging = true;
3604                     }
3605                     control.sendMouseEvent (nsEvent, DWT.MouseDown, send);
3606                     if (nsEvent.clickCount() is 2) {
3607                         control.sendMouseEvent (nsEvent, DWT.MouseDoubleClick, send);
3608                     }
3609                 }
3610                 break;
3611             }
3612             case OS.NSLeftMouseUp:
3613             case OS.NSRightMouseUp:
3614             case OS.NSOtherMouseUp: {
3615                 Control control = findControl(nsEvent, true, true, false);
3616                 if (control !is null) {
3617                     control.sendMouseEvent (nsEvent, DWT.MouseUp, send);
3618                 }
3619                 grabControl = null;
3620                 up = true;
3621                 //FALL THROUGH
3622             }
3623             case OS.NSLeftMouseDragged:
3624             case OS.NSRightMouseDragged:
3625             case OS.NSOtherMouseDragged:
3626             case OS.NSMouseMoved: {
3627                 Control control = findControl(nsEvent, true, true, type is OS.NSMouseMoved);
3628                 if (dragging) {
3629                     dragging = false;
3630                     control.sendDragEvent(nsEvent);
3631                 }
3632                 if (control !is currentControl) {
3633                     if (currentControl !is null) {
3634                         currentControl.sendMouseEvent (nsEvent, DWT.MouseExit, send);
3635                     }
3636                     currentControl = control;
3637                     if (control !is null) {
3638                         control.sendMouseEvent (nsEvent, DWT.MouseEnter, send);
3639                         if (up) timerExec (getToolTipTime (), hoverTimer);
3640                     }
3641                     setCursor (control);
3642                 }
3643                 if (!up && control !is null) {
3644                     timerExec (getToolTipTime (), hoverTimer);
3645                     control.sendMouseEvent (nsEvent, DWT.MouseMove, send);
3646                 }
3647                 break;
3648             }
3649             default:
3650         }
3651     }
3652    
3653     void applicationSendEvent (objc.id id, objc.SEL sel, objc.id event) {
3654         NSEvent nsEvent = new NSEvent(event);
3655         NSEventType type = nsEvent.type ();
3656         bool beep_ = false;
3657         switch (type) {
3658             case OS.NSLeftMouseDown:
3659             case OS.NSRightMouseDown:
3660             case OS.NSOtherMouseDown:
3661                 beep_ = true;
3662             case OS.NSLeftMouseUp:
3663             case OS.NSRightMouseUp:
3664             case OS.NSMouseMoved:
3665             case OS.NSLeftMouseDragged:
3666             case OS.NSRightMouseDragged:
3667             case OS.NSMouseEntered:
3668             case OS.NSMouseExited:
3669             case OS.NSKeyDown:
3670             case OS.NSKeyUp:
3671             case OS.NSOtherMouseUp:
3672             case OS.NSOtherMouseDragged:
3673             case OS.NSScrollWheel:
3674                 NSWindow window = nsEvent.window ();
3675                 if (window !is null) {
3676                     Shell shell = cast(Shell) getWidget (window.id);
3677                     if (shell !is null && shell.getModalShell () !is null) {
3678                         if (beep_) beep (); 
3679                         return;
3680                     }
3681                 }
3682                 break;
3683             default:
3684         }
3685         applicationSendMouseEvent (nsEvent, false);
3686         objc_super super_struct = objc_super ();
3687         super_struct.receiver = id;
3688         super_struct.super_class = cast(objc.Class) OS.objc_msgSend (id, OS.sel_superclass);
3689         OS.objc_msgSendSuper (&super_struct, sel, event);
3690         //  if (nsEvent.type() is OS.NSApplicationDefined && nsEvent.subtype() is SWT_IDLE_TYPE) {
3691         //      idle = true;
3692         //  } else {
3693         //      idle = false;
3694         //  }
3695         //  application.stop(null);
3696     }
3697    
3698     extern (C):
3699    
3700     // #245724: [NSApplication isRunning] must return true to allow the AWT to load correctly.
3701     static objc.id applicationProc2(objc.id id, objc.SEL sel) {
3702         //TODO optimize getting the display
3703         Display display = getCurrent ();
3704         if (display is null) return null;
3705         if (sel is OS.sel_isRunning) {
3706             return cast(objc.id) (display.isDisposed() ? null : cast(objc.id) 1);
3707         }
3708         return null;
3709     }
3710    
3711     static objc.id applicationProc3(objc.id id, objc.SEL sel, objc.id event) {
3712         //TODO optimize getting the display
3713         Display display = getCurrent ();
3714         if (display is null) return null;
3715         if (sel is OS.sel_sendEvent_) {
3716             display.applicationSendEvent (id, sel, event);
3717             return null;
3718         }
3719         return null;
3720     }
3721    
3722     static objc.id applicationProc6(objc.id id, objc.SEL sel, objc.id arg0, objc.id arg1, objc.id arg2, objc.id arg3) {
3723         //TODO optimize getting the display
3724         Display display = getCurrent ();
3725         if (display is null) return null;
3726         if (sel is OS.sel_nextEventMatchingMask_untilDate_inMode_dequeue_) {
3727             return display.applicationNextEventMatchingMask(id, sel, arg0, arg1, arg2, arg3);
3728         }
3729         return null;
3730     }
3731    
3732     static objc.id applicationDelegateProc(objc.id id, objc.SEL sel, objc.id arg0) {
3733         //TODO optimize getting the display
3734         Display display = getCurrent ();
3735         if (display is null) return null;
3736         cocoa.id applicationDelegate = display.applicationDelegate;
3737         NSApplication application = display.application;
3738         if (sel is OS.sel_applicationWillFinishLaunching_) {
3739             NSDictionary dict = NSDictionary.dictionaryWithObject(applicationDelegate, NSString.stringWith("NSOwner"));
3740             NSString nibFile = NSString.stringWith("/System/Library/Frameworks/JavaVM.framework/Resources/English.lproj/DefaultApp.nib");
3741             if (!NSBundle.loadNibFile(nibFile, dict, null)) {
3742                 nibFile = NSString.stringWith("/System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Resources/English.lproj/DefaultApp.nib");
3743                 NSBundle.loadNibFile(nibFile, dict, null);
3744             }
3745             //replace %@ with application name
3746             NSMenu mainmenu = application.mainMenu();
3747             NSMenuItem appitem = mainmenu.itemAtIndex(0);
3748             if (appitem !is null) {
3749                 NSMenu sm = appitem.submenu();
3750                 NSArray ia = sm.itemArray();
3751                 for(int i = 0; i < ia.count(); i++) {
3752                     NSMenuItem ni = new NSMenuItem(ia.objectAtIndex(i));
3753                     NSString title = ni.title().stringByReplacingOccurrencesOfString(NSString.stringWith("%@"), NSString.stringWith(APP_NAME));
3754                     ni.setTitle(title);
3755                 }
3756             }
3757         } else if (sel is OS.sel_terminate_) {
3758             application.terminate(application);
3759         } else if (sel is OS.sel_orderFrontStandardAboutPanel_) {
3760             //      Event event = new Event ();
3761             //      sendEvent (DWT.ABORT, event);
3762         } else if (sel is OS.sel_hideOtherApplications_) {
3763             application.hideOtherApplications(application);
3764         } else if (sel is OS.sel_hide_) {
3765             application.hide(application);
3766         } else if (sel is OS.sel_unhideAllApplications_) {
3767             application.unhideAllApplications(application);
3768         } else if (sel is OS.sel_applicationShouldTerminate_) {
3769             if (!display.disposing) {
3770                 Event event = new Event ();
3771                 display.sendEvent (DWT.Close, event);
3772                 if (event.doit) {
3773                     return cast(objc.id) OS.NSTerminateNow;
3774                 }
3775             }
3776             return cast(objc.id) OS.NSTerminateCancel;
3777         } else if (sel is OS.sel_applicationWillTerminate_) {
3778             display.dispose();
3779         } else if (sel is OS.sel_applicationWillResignActive_) {
3780             Shell[] shells = display.getShells();
3781             for (int i = 0; i < shells.length; i++) {
3782                 shells[i].clearLevel();
3783             }
3784         }
3785         return null;
3786     }
3787    
3788     static objc.id dialogProc(objc.id id, objc.SEL sel, objc.id arg0) {
3789         void* jniRef;
3790         OS.object_getInstanceVariable(id, SWT_OBJECT, jniRef);
3791         if (jniRef is null) return null;
3792         if (sel is OS.sel_changeColor_) {
3793             ColorDialog dialog = cast(ColorDialog)OS.JNIGetObject(jniRef);
3794             if (jniRef is null) return null;
3795             dialog.changeColor(id, sel, arg0);
3796         } else if (sel is OS.sel_changeFont_) {
3797             FontDialog dialog = cast(FontDialog)OS.JNIGetObject(jniRef);
3798             if (dialog is null) return null;
3799             dialog.changeFont(id, sel, arg0);
3800         } else if (sel is OS.sel_windowWillClose_) {
3801             Object object = OS.JNIGetObject(jniRef);
3802             if (cast(FontDialog) object) {
3803                 (cast(FontDialog)object).windowWillClose(id, sel, arg0);
3804             } else if (cast(ColorDialog) object) {
3805                 (cast(ColorDialog)object).windowWillClose(id, sel, arg0);
3806             }
3807         }
3808         return null;
3809     }
3810    
3811     static objc.id windowDelegateProc2(objc.id id, objc.SEL sel) {
3812         Widget widget = GetWidget(id);
3813         if (widget is null) return null;
3814         if (sel is OS.sel_sendSelection) {
3815             widget.sendSelection();
3816         } else if (sel is OS.sel_sendDoubleSelection) {
3817             widget.sendDoubleSelection();
3818         } else if (sel is OS.sel_sendVerticalSelection) {
3819             widget.sendVerticalSelection();
3820         } else if (sel is OS.sel_sendHorizontalSelection) {
3821             widget.sendHorizontalSelection();
3822         } else if (sel is OS.sel_acceptsFirstResponder) {
3823             return widget.acceptsFirstResponder(id, sel) ? cast(objc.id) 1 : null;
3824         } else if (sel is OS.sel_becomeFirstResponder) {
3825             return widget.becomeFirstResponder(id, sel) ? cast(objc.id) 1 : null;
3826         } else if (sel is OS.sel_resignFirstResponder) {
3827             return widget.resignFirstResponder(id, sel) ? cast(objc.id) 1 : null;
3828         } else  if (sel is OS.sel_isFlipped) {
3829             return widget.isFlipped(id, sel) ? cast(objc.id) 1 : null;
3830         } else if (sel is OS.sel_isOpaque) {
3831             return widget.isOpaque(id, sel) ? cast(objc.id) 1 : null;
3832         } else if (sel is OS.sel_unmarkText) {
3833             //TODO not called?
3834         } else if (sel is OS.sel_validAttributesForMarkedText) {
3835             return widget.validAttributesForMarkedText (id, sel);
3836         } else if (sel is OS.sel_markedRange) {
3837             NSRange range = widget.markedRange (id, sel);
3838             /* NOTE that this is freed in C */
3839             objc.id result = cast(objc.id) OS.malloc (NSRange.sizeof);
3840             OS.memmove (result, &range, NSRange.sizeof);
3841             return result;
3842         } else if (sel is OS.sel_selectedRange) {
3843             NSRange range = widget.selectedRange (id, sel);
3844             /* NOTE that this is freed in C */
3845             objc.id result = cast(objc.id) OS.malloc (NSRange.sizeof);
3846             OS.memmove (result, &range, NSRange.sizeof);
3847             return result;
3848         } else if (sel is OS.sel_hasMarkedText) {
3849             return widget.hasMarkedText (id, sel) ? cast(objc.id) 1 : null;
3850         } else if (sel is OS.sel_canBecomeKeyWindow) {
3851             return widget.canBecomeKeyWindow (id, sel) ? cast(objc.id) 1 : null;
3852         } else if (sel is OS.sel_accessibilityActionNames) {
3853             return widget.accessibilityActionNames(id, sel);
3854         } else if (sel is OS.sel_accessibilityAttributeNames) {
3855             return widget.accessibilityAttributeNames(id, sel);
3856         } else if (sel is OS.sel_accessibilityParameterizedAttributeNames) {
3857             return widget.accessibilityParameterizedAttributeNames(id, sel);
3858         } else if (sel is OS.sel_accessibilityFocusedUIElement) {
3859             return widget.accessibilityFocusedUIElement(id, sel);
3860         } else if (sel is OS.sel_accessibilityIsIgnored) {
3861             return (widget.accessibilityIsIgnored(id, sel) ? cast(objc.id) 1 : null);
3862         }
3863         return null;
3864     }
3865    
3866     static objc.id windowDelegateProc3(objc.id id, objc.SEL sel, objc.id arg0) {
3867         if (sel is OS.sel_timerProc_) {
3868             //TODO optimize getting the display
3869             Display display = getCurrent ();
3870             if (display is null) return null;
3871             return display.timerProc (id, sel, arg0);
3872         }
3873         Widget widget = GetWidget(id);
3874         if (widget is null && (sel is OS.sel_keyDown_ ||sel is OS.sel_keyUp_ ||sel is OS.sel_insertText_ ||sel is OS.sel_doCommandBySelector_))  {
3875             widget = GetFocusControl ((new NSView (id)).window ());
3876         }
3877         if (widget is null) return null;
3878         if (sel is OS.sel_windowWillClose_) {
3879             widget.windowWillClose(id, sel, arg0);
3880         } else if (sel is OS.sel_drawRect_) {
3881             NSRect rect = NSRect();
3882             OS.memmove(&rect, arg0, NSRect.sizeof);
3883             widget.drawRect(id, sel, rect);
3884         } else if (sel is OS.sel_setFrameOrigin_) {
3885             NSPoint point = NSPoint();
3886             OS.memmove(&point, arg0, NSPoint.sizeof);
3887             widget.setFrameOrigin(id, sel, point);
3888         } else if (sel is OS.sel_setFrameSize_) {
3889             NSSize size = NSSize();
3890             OS.memmove(&size, arg0, NSSize.sizeof);
3891             widget.setFrameSize(id, sel, size);
3892         } else if (sel is OS.sel_hitTest_) {
3893             NSPoint point = NSPoint();
3894             OS.memmove(&point, arg0, NSPoint.sizeof);
3895             return widget.hitTest(id, sel, point);
3896         } else if (sel is OS.sel_windowShouldClose_) {
3897             return widget.windowShouldClose(id, sel, arg0) ? cast(objc.id) 1 : null;
3898         } else if (sel is OS.sel_mouseDown_) {
3899             widget.mouseDown(id, sel, arg0);
3900         } else if (sel is OS.sel_keyDown_) {
3901             widget.keyDown(id, sel, arg0);
3902         } else if (sel is OS.sel_keyUp_) {
3903             widget.keyUp(id, sel, arg0);
3904         } else if (sel is OS.sel_flagsChanged_) {
3905             widget.flagsChanged(id, sel, arg0);
3906         } else if (sel is OS.sel_mouseUp_) {
3907             widget.mouseUp(id, sel, arg0);
3908         } else if (sel is OS.sel_rightMouseDown_) {
3909             widget.rightMouseDown(id, sel, arg0);
3910         } else if (sel is OS.sel_rightMouseUp_) {
3911             widget.rightMouseUp(id, sel, arg0);
3912         } else if (sel is OS.sel_otherMouseDown_) {
3913             widget.otherMouseDown(id, sel, arg0);
3914         } else if (sel is OS.sel_otherMouseUp_) {
3915             widget.otherMouseUp(id, sel, arg0);
3916         } else if (sel is OS.sel_mouseMoved_) {
3917             widget.mouseMoved(id, sel, arg0);
3918         } else if (sel is OS.sel_mouseDragged_) {
3919             widget.mouseDragged(id, sel, arg0);
3920         } else if (sel is OS.sel_mouseEntered_) {
3921             widget.mouseEntered(id, sel, arg0);
3922         } else if (sel is OS.sel_mouseExited_) {
3923             widget.mouseExited(id, sel, arg0);
3924         } else if (sel is OS.sel_menuForEvent_) {
3925             return widget.menuForEvent(id, sel, arg0);
3926         } else if (sel is OS.sel_numberOfRowsInTableView_) {
3927             return cast(objc.id) widget.numberOfRowsInTableView(id, sel, arg0);
3928         } else if (sel is OS.sel_comboBoxSelectionDidChange_) {
3929             widget.comboBoxSelectionDidChange(id, sel, arg0);
3930         } else if (sel is OS.sel_tableViewSelectionDidChange_) {
3931             widget.tableViewSelectionDidChange(id, sel, arg0);
3932         } else if (sel is OS.sel_windowDidResignKey_) {
3933             widget.windowDidResignKey(id, sel, arg0);
3934         } else if (sel is OS.sel_windowDidBecomeKey_) {
3935             widget.windowDidBecomeKey(id, sel, arg0);
3936         } else if (sel is OS.sel_windowDidResize_) {
3937             widget.windowDidResize(id, sel, arg0);
3938         } else if (sel is OS.sel_windowDidMove_) {
3939             widget.windowDidMove(id, sel, arg0);
3940         } else if (sel is OS.sel_menuWillOpen_) {
3941             widget.menuWillOpen(id, sel, arg0);
3942         } else if (sel is OS.sel_menuDidClose_) {
3943             widget.menuDidClose(id, sel, arg0);
3944         } else if (sel is OS.sel_menuNeedsUpdate_) {
3945             widget.menuNeedsUpdate(id, sel, arg0);
3946         } else if (sel is OS.sel_outlineViewSelectionDidChange_) {
3947             widget.outlineViewSelectionDidChange(id, sel, arg0);
3948         } else if (sel is OS.sel_outlineViewItemDidExpand_) {
3949             widget.outlineViewItemDidExpand(id, sel, arg0);
3950         } else if (sel is OS.sel_sendEvent_) {
3951             widget.windowSendEvent(id, sel, arg0);
3952         } else if (sel is OS.sel_helpRequested_) {
3953             widget.helpRequested(id, sel, arg0);
3954         } else if (sel is OS.sel_scrollWheel_) {
3955             widget.scrollWheel(id, sel, arg0);
3956         } else if (sel is OS.sel_pageDown_) {
3957             widget.pageDown(id, sel, arg0);
3958         } else if (sel is OS.sel_pageUp_) {
3959             widget.pageUp(id, sel, arg0);
3960         } else if (sel is OS.sel_textViewDidChangeSelection_) {
3961             widget.textViewDidChangeSelection(id, sel, arg0);
3962         } else if (sel is OS.sel_textDidChange_) {
3963             widget.textDidChange(id, sel, arg0);
3964         } else if (sel is OS.sel_attributedSubstringFromRange_) {
3965             return widget.attributedSubstringFromRange (id, sel, arg0);
3966         } else if (sel is OS.sel_characterIndexForPoint_) {
3967             return cast(objc.id) widget.characterIndexForPoint (id, sel, arg0);
3968         } else if (sel is OS.sel_firstRectForCharacterRange_) {
3969             NSRect rect = widget.firstRectForCharacterRange (id, sel, arg0);
3970             /* NOTE that this is freed in C */
3971             objc.id result = cast(objc.id) OS.malloc (NSRect.sizeof);
3972             OS.memmove (result, &rect, NSRect.sizeof);
3973             return result;
3974         } else if (sel is OS.sel_insertText_) {
3975             widget.insertText (id, sel, arg0);
3976         } else if (sel is OS.sel_doCommandBySelector_) {
3977             widget.doCommandBySelector (id, sel, cast(objc.SEL) arg0);
3978         } else if (sel is OS.sel_highlightSelectionInClipRect_) {
3979             widget.highlightSelectionInClipRect (id, sel, arg0);
3980         } else if (sel is OS.sel_reflectScrolledClipView_) {
3981             widget.reflectScrolledClipView (id, sel, arg0);
3982         } else if (sel is OS.sel_accessibilityHitTest_) {
3983             NSPoint point = NSPoint();
3984             OS.memmove(&point, arg0, NSPoint.sizeof);
3985             return widget.accessibilityHitTest(id, sel, point);
3986         } else if (sel is OS.sel_accessibilityAttributeValue_) {
3987             return widget.accessibilityAttributeValue(id, sel, arg0);
3988         } else if (sel is OS.sel_accessibilityIsAttributeSettable_) {
3989             return (widget.accessibilityIsAttributeSettable(id, sel, arg0) ? cast(objc.id) 1 : null);
3990         } else if (sel is OS.sel_accessibilityPerformAction_) {
3991             widget.accessibilityPerformAction(id, sel, arg0);
3992         } else if (sel is OS.sel_accessibilityActionDescription_) {
3993             widget.accessibilityActionDescription(id, sel, arg0);
3994         } else if (sel is OS.sel_makeFirstResponder_) {
3995             return widget.makeFirstResponder(id, sel, arg0) ? cast(objc.id) 1 : null;
3996         } else if (sel is OS.sel_tableViewColumnDidMove_) {
3997             widget.tableViewColumnDidMove(id, sel, arg0);
3998         } else if (sel is OS.sel_tableViewColumnDidResize_) {
3999             widget.tableViewColumnDidResize(id, sel, arg0);
4000         } else if (sel is OS.sel_outlineViewColumnDidMove_) {
4001             widget.outlineViewColumnDidMove(id, sel, arg0);
4002         } else if (sel is OS.sel_outlineViewColumnDidResize_) {
4003             widget.outlineViewColumnDidResize(id, sel, arg0);
4004         }
4005         return null;
4006     }
4007    
4008     static objc.id windowDelegateProc4(objc.id id, objc.SEL sel, objc.id arg0, objc.id arg1) {
4009         Widget widget = GetWidget(id);
4010         if (widget is null) return null;
4011         if (sel is OS.sel_tabView_willSelectTabViewItem_) {
4012             widget.tabView_willSelectTabViewItem(id, sel, arg0, arg1);
4013         } else if (sel is OS.sel_tabView_didSelectTabViewItem_) {
4014             widget.tabView_didSelectTabViewItem(id, sel, arg0, arg1);
4015         } else if (sel is OS.sel_outlineView_isItemExpandable_) {
4016             return widget.outlineView_isItemExpandable(id, sel, arg0, arg1) ? cast(objc.id) 1 : null;
4017         } else if (sel is OS.sel_outlineView_numberOfChildrenOfItem_) {
4018             return cast(objc.id) widget.outlineView_numberOfChildrenOfItem(id, sel, arg0, arg1);
4019         } else if (sel is OS.sel_outlineView_shouldCollapseItem_) {
4020             return widget.outlineView_shouldCollapseItem(id, sel, arg0, arg1) ? cast(objc.id) 1 : null;
4021         } else if (sel is OS.sel_outlineView_shouldExpandItem_) {
4022             return widget.outlineView_shouldExpandItem(id, sel, arg0, arg1) ? cast(objc.id) 1 : null;
4023         } else if (sel is OS.sel_menu_willHighlightItem_) {
4024             widget.menu_willHighlightItem(id, sel, arg0, arg1);
4025         } else if (sel is OS.sel_setMarkedText_selectedRange_) {
4026             widget.setMarkedText_selectedRange (id, sel, arg0, arg1);
4027         } else if (sel is OS.sel_drawInteriorWithFrame_inView_) {
4028             widget.drawInteriorWithFrame_inView (id, sel, arg0, arg1);
4029         } else if (sel is OS.sel_accessibilityAttributeValue_forParameter_) {
4030             return widget.accessibilityAttributeValue_forParameter(id, sel, arg0, arg1);
4031         } else if (sel is OS.sel_tableView_didClickTableColumn_) {
4032             widget.tableView_didClickTableColumn (id, sel, arg0, arg1);
4033         } else if (sel is OS.sel_outlineView_didClickTableColumn_) {
4034             widget.outlineView_didClickTableColumn (id, sel, arg0, arg1);
4035         }
4036         return null;
4037     }
4038    
4039     static objc.id windowDelegateProc5(objc.id id, objc.SEL sel, objc.id arg0, objc.id arg1, objc.id arg2) {
4040         Widget widget = GetWidget(id);
4041         if (widget is null) return null;
4042         if (sel is OS.sel_tableView_objectValueForTableColumn_row_) {
4043             return widget.tableView_objectValueForTableColumn_row(id, sel, arg0, arg1, arg2);
4044         } else if (sel is OS.sel_tableView_shouldEditTableColumn_row_) {
4045             return widget.tableView_shouldEditTableColumn_row(id, sel, arg0, arg1, arg2) ? cast(objc.id) 1 : null;
4046         } else if (sel is OS.sel_textView_clickedOnLink_atIndex_) {
4047             return widget.textView_clickOnLink_atIndex(id, sel, arg0, arg1, arg2) ? cast(objc.id) 1 : null;
4048         } else if (sel is OS.sel_outlineView_child_ofItem_) {
4049             return widget.outlineView_child_ofItem(id, sel, arg0, arg1, arg2);
4050         } else if (sel is OS.sel_outlineView_objectValueForTableColumn_byItem_) {
4051             return widget.outlineView_objectValueForTableColumn_byItem(id, sel, arg0, arg1, arg2);
4052         } else if (sel is OS.sel_textView_willChangeSelectionFromCharacterRange_toCharacterRange_) {
4053             NSRange range = widget.textView_willChangeSelectionFromCharacterRange_toCharacterRange(id, sel, arg0, arg1, arg2);
4054             /* NOTE that this is freed in C */
4055             objc.id result = cast(objc.id) OS.malloc (NSRange.sizeof);
4056             OS.memmove (result, &range, NSRange.sizeof);
4057             return result;
4058         }
4059         return null;
4060     }
4061    
4062     static objc.id windowDelegateProc6(objc.id id, objc.SEL sel, objc.id arg0, objc.id arg1, objc.id arg2, objc.id arg3) {
4063         Widget widget = GetWidget(id);
4064         if (widget is null) return null;
4065         if (sel is OS.sel_tableView_willDisplayCell_forTableColumn_row_) {
4066             widget.tableView_willDisplayCell_forTableColumn_row(id, sel, arg0, arg1, arg2, arg3);
4067         } else if (sel is OS.sel_outlineView_willDisplayCell_forTableColumn_item_) {
4068             widget.outlineView_willDisplayCell_forTableColumn_item(id, sel, arg0, arg1, arg2, arg3);
4069         } else  if (sel is OS.sel_outlineView_setObjectValue_forTableColumn_byItem_) {
4070             widget.outlineView_setObjectValue_forTableColumn_byItem(id, sel, arg0, arg1, arg2, arg3);
4071         } else if (sel is OS.sel_tableView_setObjectValue_forTableColumn_row_) {
4072             widget.tableView_setObjectValue_forTableColumn_row(id, sel, arg0, arg1, arg2, arg3);
4073         }
4074         return null;
4075     }
4076     }
Note: See TracBrowser for help on using the browser.