diff dwt/widgets/Display.d @ 213:36f5cb12e1a2

Update to SWT 3.4M7
author Frank Benoit <benoit@tionex.de>
date Sat, 17 May 2008 17:34:28 +0200
parents ab60f3309436
children a8fed3e56433
line wrap: on
line diff
--- a/dwt/widgets/Display.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Display.d	Sat May 17 17:34:28 2008 +0200
@@ -30,9 +30,11 @@
 import dwt.graphics.Rectangle;
 import dwt.graphics.Resource;
 import dwt.internal.ImageList;
+import dwt.internal.Library;
 import dwt.internal.win32.OS;
 
 import dwt.widgets.Control;
+import dwt.widgets.Dialog;
 import dwt.widgets.Tray;
 import dwt.widgets.Event;
 import dwt.widgets.EventTable;
@@ -143,7 +145,7 @@
      * platforms and should never be accessed from application code.
      * </p>
      */
-    public MSG msg;
+    public MSG* msg;
 
     /* Windows and Events */
     Event [] eventQueue;
@@ -157,9 +159,9 @@
     EventTable eventTable, filterTable;
 
     /* Widget Table */
+    int freeSlot;
     int [] indexTable;
     Control lastControl, lastGetControl;
-    int freeSlot;
     HANDLE lastHwnd;
     HWND lastGetHwnd;
     Control [] controlTable;
@@ -228,8 +230,8 @@
     //Callback msgFilterCallback;
     //int msgFilterProc_,
     HHOOK filterHook;
-    MSG hookMsg;
-    bool runDragDrop = true;
+    bool runDragDrop = true, dragCancelled = false;
+    MSG* hookMsg;
 
     /* Idle Hook */
     //Callback foregroundIdleCallback;
@@ -248,8 +250,9 @@
 
     /* Sync/Async Widget Communication */
     Synchronizer synchronizer;
-    bool runMessages = true, runMessagesInIdle = false;
+    bool runMessages = true, runMessagesInIdle = false, runMessagesInMessageProc = true;
     static const String RUN_MESSAGES_IN_IDLE_KEY = "org.eclipse.swt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$
+    static final String RUN_MESSAGES_IN_MESSAGE_PROC_KEY = "dwt.internal.win32.runMessagesInMessageProc"; //$NON-NLS-1$
     Thread thread;
 
     /* Display Shutdown */
@@ -260,16 +263,17 @@
     int nextTrayId;
 
     /* Timers */
-    int [] timerIds;
+    int /*long*/ [] timerIds;
     Runnable [] timerList;
-    int nextTimerId = SETTINGS_ID + 1;
+    int /*long*/ nextTimerId = SETTINGS_ID + 1;
     static const int SETTINGS_ID = 100;
     static const int SETTINGS_DELAY = 2000;
 
     /* Keyboard and Mouse */
-    RECT clickRect;
+    RECT* clickRect;
     int clickCount, lastTime, lastButton;
     HWND lastClickHwnd;
+    int scrollRemainder;
     int lastKey, lastAscii, lastMouse;
     bool lastVirtual, lastNull, lastDead;
     ubyte [256] keyboard;
@@ -308,6 +312,15 @@
 
     /* Table */
     char [] tableBuffer;
+    NMHDR* hdr;
+    NMLVDISPINFO* plvfi;
+    HWND hwndParent;
+    int columnCount;
+    bool [] columnVisible;
+
+    /* Resize and move recursion */
+    int resizeCount;
+    static final int RESIZE_LIMIT = 4;
 
     /* Display Data */
     Object data;
@@ -404,7 +417,7 @@
 
     /* Modality */
     Shell [] modalShells;
-    Shell modalDialogShell;
+    Dialog modalDialog;
     static bool TrimEnabled = false;
 
     /* Private DWT Window Messages */
@@ -417,6 +430,7 @@
     static const int SWT_RUNASYNC       = OS.WM_APP + 6;
     static int SWT_TASKBARCREATED;
     static int SWT_RESTORECARET;
+    static int DI_GETDRAGIMAGE;
 
     /* Workaround for Adobe Reader 7.0 */
     int hitCount;
@@ -490,6 +504,8 @@
  */
 public this (DeviceData data) {
     static_this();
+    msg = new MSG();
+    hookMsg = new MSG();
     super (data);
     synchronizer = new Synchronizer (this);
     cursors = new Cursor [DWT.CURSOR_HAND + 1];
@@ -534,7 +550,7 @@
     static if (USE_PROPERTY) {
         OS.SetProp (handle, cast(wchar*)SWT_OBJECT_INDEX, cast(void*) freeSlot + 1);
     } else {
-        OS.SetWindowLong (handle, OS.GWL_USERDATA, freeSlot + 1);
+        OS.SetWindowLongPtr (handle, OS.GWLP_USERDATA, freeSlot + 1);
     }
     int oldSlot = freeSlot;
     freeSlot = indexTable [oldSlot];
@@ -692,8 +708,10 @@
  * @see #syncExec
  */
 public void asyncExec (Runnable runnable) {
-    if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
-    synchronizer.asyncExec (runnable);
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
+        synchronizer.asyncExec (runnable);
+    }
 }
 
 /**
@@ -732,11 +750,13 @@
     if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
 }
 
-static synchronized void checkDisplay (Thread thread, bool multiple) {
-    for (int i=0; i<Displays.length; i++) {
-        if (Displays [i] !is null) {
-            if (!multiple) DWT.error (DWT.ERROR_NOT_IMPLEMENTED, null, " [multiple displays]");
-            if (Displays [i].thread is thread) DWT.error (DWT.ERROR_THREAD_INVALID_ACCESS);
+static void checkDisplay (Thread thread, bool multiple) {
+    synchronized (Device.classinfo) {
+        for (int i=0; i<Displays.length; i++) {
+            if (Displays [i] !is null) {
+                if (!multiple) DWT.error (DWT.ERROR_NOT_IMPLEMENTED, null, " [multiple displays]"); //$NON-NLS-1$
+                if (Displays [i].thread is thread) DWT.error (DWT.ERROR_THREAD_INVALID_ACCESS);
+            }
         }
     }
 }
@@ -845,8 +865,8 @@
     bmiHeader.biCompression = OS.BI_RGB;
     byte [] bmi = new byte [BITMAPINFOHEADER.sizeof];
     bmi[ 0 .. BITMAPINFOHEADER.sizeof ] = (cast(byte*)&bmiHeader)[ 0 .. BITMAPINFOHEADER.sizeof ];
-    int[1] pBits;
-    auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, pBits.ptr, null, 0);
+    void* pBits;
+    auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
     if (memDib is null) DWT.error (DWT.ERROR_NO_HANDLES);
     auto oldMemBitmap = OS.SelectObject (memHdc, memDib);
     BITMAP dibBM;
@@ -882,7 +902,7 @@
             }
         }
     }
-    byte [] srcData = (cast(byte*)pBits [0])[ 0 .. sizeInBytes].dup;
+    byte [] srcData = (cast(byte*)pBits)[ 0 .. sizeInBytes].dup;
     if (hMask !is null) {
         OS.SelectObject(srcHdc, hMask);
         for (int y = 0, dp = 0; y < imgHeight; ++y) {
@@ -930,7 +950,7 @@
             }
         }
     }
-    (cast(byte*)pBits [0])[ 0 .. sizeInBytes] = srcData[];
+    (cast(byte*)pBits)[ 0 .. sizeInBytes] = srcData[];
     OS.SelectObject (srcHdc, oldSrcBitmap);
     OS.SelectObject (memHdc, oldMemBitmap);
     OS.DeleteObject (srcHdc);
@@ -959,8 +979,8 @@
     bmiHeader.biBitCount = cast(short)32;
     bmiHeader.biCompression = OS.BI_RGB;
     byte [] bmi = (cast(byte*)&bmiHeader)[ 0 .. BITMAPINFOHEADER.sizeof];
-    int [1] pBits;
-    auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, pBits.ptr, null, 0);
+    void* pBits;
+    auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
     if (memDib is null) DWT.error (DWT.ERROR_NO_HANDLES);
     auto oldMemBitmap = OS.SelectObject (memHdc, memDib);
     BITMAP dibBM;
@@ -1001,7 +1021,7 @@
     OS.DeleteObject (srcHdc);
     OS.DeleteObject (memHdc);
     OS.ReleaseDC (null, hDC);
-    byte [] srcData = (cast(byte*)pBits[0])[ 0 .. sizeInBytes ].dup;
+    byte [] srcData = (cast(byte*)pBits)[ 0 .. sizeInBytes ].dup;
     if (alpha !is -1) {
         for (int y = 0, dp = 0; y < imgHeight; ++y) {
             for (int x = 0; x < imgWidth; ++x) {
@@ -1028,7 +1048,7 @@
             }
         }
     }
-    (cast(byte*)pBits[0])[ 0 .. sizeInBytes ] = srcData[];
+    (cast(byte*)pBits)[ 0 .. sizeInBytes ] = srcData[];
     return memDib;
 }
 
@@ -1112,10 +1132,11 @@
     return hMask;
 }
 
-static synchronized void deregister (Display display) {
-    static_this();
-    for (int i=0; i<Displays.length; i++) {
-        if (display is Displays [i]) Displays [i] = null;
+static void deregister (Display display) {
+    synchronized (Device.classinfo) {
+        for (int i=0; i<Displays.length; i++) {
+            if (display is Displays [i]) Displays [i] = null;
+        }
     }
 }
 
@@ -1294,6 +1315,7 @@
  */
 public Widget findWidget (HANDLE handle, int id) {
     checkDevice ();
+    //TODO - should ids be long
     Control control = getControl (handle);
     return control !is null ? control.findItem (cast(HANDLE) id) : null;
 }
@@ -1315,8 +1337,9 @@
  *
  * @since 3.3
  */
-public Widget findWidget (Widget widget, int id) {
+public Widget findWidget (Widget widget, int /*long*/ id) {
     checkDevice ();
+    //TODO - should ids be long
     if (cast(Control)widget) {
         return findWidget ((cast(Control) widget).handle, id);
     }
@@ -1329,14 +1352,16 @@
 }
 
 int foregroundIdleProc (int code, int wParam, int lParam) {
-    if (runMessages) {
-        if (code >= 0) {
-            if (getMessageCount () !is 0) {
-                if (runMessagesInIdle) {
+    if (code >= 0) {
+        if (runMessages && getMessageCount () !is 0) {
+            if (runMessagesInIdle) {
+                if (runMessagesInMessageProc) {
                     OS.PostMessage (hwndMessage, SWT_RUNASYNC, 0, 0);
+                } else {
+                    runAsyncMessages (false);
                 }
-                wakeThread ();
             }
+            wakeThread ();
         }
     }
     return OS.CallNextHookEx (idleHook, code, wParam, lParam);
@@ -1352,15 +1377,17 @@
  * @param thread the user-interface thread
  * @return the display for the given thread
  */
-public static synchronized Display findDisplay (Thread thread) {
+public static Display findDisplay (Thread thread) {
     static_this();
-    for (int i=0; i<Displays.length; i++) {
-        Display display = Displays [i];
-        if (display !is null && display.thread is thread) {
-            return display;
+    synchronized (Device.classinfo) {
+        for (int i=0; i<Displays.length; i++) {
+            Display display = Displays [i];
+            if (display !is null && display.thread is thread) {
+                return display;
+            }
         }
+        return null;
     }
-    return null;
 }
 
 /**
@@ -1382,7 +1409,8 @@
 }
 
 /**
- * Returns a rectangle describing the receiver's size and location.
+ * Returns a rectangle describing the receiver's size and location. Note that
+ * on multi-monitor systems the origin can be negative.
  *
  * @return the bounding rectangle
  *
@@ -1412,7 +1440,7 @@
  *
  * @return the current display
  */
-public static synchronized Display getCurrent () {
+public static Display getCurrent () {
     static_this();
     return findDisplay (Thread.getThis ());
 }
@@ -1421,12 +1449,11 @@
     switch (type) {
         case DWT.MouseDown:
             int doubleClick = OS.GetDoubleClickTime ();
-            //if (clickRect is null) clickRect = new RECT ();
+            if (clickRect is null) clickRect = new RECT ();
             int deltaTime = Math.abs (lastTime - getLastEventTime ());
             POINT pt;
-            pt.x = cast(short) (lParam & 0xFFFF);
-            pt.y = cast(short) (lParam >> 16);
-            if (lastClickHwnd is hwnd && lastButton is button && (deltaTime <= doubleClick) && OS.PtInRect (&clickRect, pt)) {
+            OS.POINTSTOPOINT (pt, lParam);
+            if (lastClickHwnd is hwnd && lastButton is button && (deltaTime <= doubleClick) && OS.PtInRect (clickRect, pt)) {
                 clickCount++;
             } else {
                 clickCount = 1;
@@ -1438,8 +1465,8 @@
             lastTime = getLastEventTime ();
             int xInset = OS.GetSystemMetrics (OS.SM_CXDOUBLECLK) / 2;
             int yInset = OS.GetSystemMetrics (OS.SM_CYDOUBLECLK) / 2;
-            int x = cast(short) (lParam & 0xFFFF), y = cast(short) (lParam >> 16);
-            OS.SetRect (&clickRect, x - xInset, y - yInset, x + xInset, y + yInset);
+            int x = OS.GET_X_LPARAM (lParam), y = OS.GET_Y_LPARAM (lParam);
+            OS.SetRect (clickRect, x - xInset, y - yInset, x + xInset, y + yInset);
             //FALL THROUGH
         case DWT.MouseUp:
             return clickCount;
@@ -1489,7 +1516,7 @@
     static if (USE_PROPERTY) {
         index = cast(int) OS.GetProp (handle, cast(wchar*)SWT_OBJECT_INDEX) - 1;
     } else {
-        index = OS.GetWindowLong (handle, OS.GWL_USERDATA) - 1;
+        index = OS.GetWindowLongPtr (handle, OS.GWLP_USERDATA) - 1;
     }
     if (0 <= index && index < controlTable.length) {
         Control control = controlTable [index];
@@ -1572,10 +1599,12 @@
  *
  * @return the default display
  */
-public static synchronized Display getDefault () {
+public static Display getDefault () {
     static_this();
-    if (Default is null) Default = new Display ();
-    return Default;
+    synchronized (Device.classinfo) {
+        if (Default is null) Default = new Display ();
+        return Default;
+    }
 }
 
 //PORTING_TODO
@@ -1616,6 +1645,9 @@
     if (key ==/*eq*/RUN_MESSAGES_IN_IDLE_KEY) {
         return new ValueWrapperBool(runMessagesInIdle);
     }
+    if (key.equals (RUN_MESSAGES_IN_MESSAGE_PROC_KEY)) {
+        return new Boolean (runMessagesInMessageProc);
+    }
     if (keys.length is 0) return null;
     for (int i=0; i<keys.length; i++) {
         if (keys [i] ==/*eq*/key) return values [i];
@@ -1967,9 +1999,8 @@
     return null;
 }
 
-Shell getModalDialogShell () {
-    if (modalDialogShell !is null && modalDialogShell.isDisposed ()) modalDialogShell = null;
-    return modalDialogShell;
+Dialog getModalDialog () {
+    return modalDialog;
 }
 
 /**
@@ -2012,9 +2043,9 @@
         //embeddedCallback = new Callback (this, "embeddedProc", 4); //$NON-NLS-1$
         //embeddedProc_ = embeddedCallback.getAddress ();
         //if (embeddedProc_ is 0) error (DWT.ERROR_NO_MORE_CALLBACKS);
-        OS.SetWindowLong (embeddedHwnd, OS.GWL_WNDPROC, cast(int) &embeddedFunc);
+        OS.SetWindowLongPtr (embeddedHwnd, OS.GWLP_WNDPROC, cast(LONG_PTR) &embeddedFunc);
     }
-    if (code >= 0 && wParam !is OS.PM_NOREMOVE) {
+    if (code >= 0 && (wParam & OS.PM_REMOVE) !is 0) {
         MSG* msg = cast(MSG*)lParam;
         switch (msg.message) {
             case OS.WM_KEYDOWN:
@@ -2167,6 +2198,23 @@
 }
 
 /**
+ * Gets the synchronizer used by the display.
+ *
+ * @return the receiver's synchronizer
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public Synchronizer getSynchronizer () {
+    checkDevice ();
+    return synchronizer;
+}
+
+/**
  * Returns the thread that has invoked <code>syncExec</code>
  * or null if no such runnable is currently being invoked by
  * the user-interface thread.
@@ -2182,8 +2230,10 @@
  * </ul>
  */
 public Thread getSyncThread () {
-    if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
-    return synchronizer.syncThread;
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
+        return synchronizer.syncThread;
+    }
 }
 
 /**
@@ -2414,8 +2464,10 @@
  * </ul>
  */
 public Thread getThread () {
-    if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
-    return thread;
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
+        return thread;
+    }
 }
 
 HTHEME hButtonTheme () {
@@ -2475,7 +2527,7 @@
             data.style |= DWT.LEFT_TO_RIGHT;
         }
         data.device = this;
-        data.hFont = getSystemFont ().handle;
+        data.font = getSystemFont ();
     }
     return hDC;
 }
@@ -2513,6 +2565,29 @@
     lpWndClass.lpfnWndProc = &windowProcFunc;
     lpWndClass.style = OS.CS_BYTEALIGNWINDOW | OS.CS_DBLCLKS;
     lpWndClass.hCursor = OS.LoadCursor (null, cast(wchar*)OS.IDC_ARROW);
+
+
+    //DWT_TODO: Check if this can be disabled for DWT
+    /+
+    /*
+    * Set the default icon for the window class to IDI_APPLICATION.
+    * This is not necessary for native Windows applications but
+    * versions of Java starting at JDK 1.6 set the icon in the
+    * executable instead of leaving the default.
+    */
+    if (!OS.IsWinCE && Library.JAVA_VERSION >= Library.JAVA_VERSION (1, 6, 0)) {
+        TCHAR[] lpszFile = NewTCHARs (0, OS.MAX_PATH);
+        while (OS.GetModuleFileName (0, lpszFile.ptr, lpszFile.length) is lpszFile.length) {
+            lpszFile = NewTCHARs (0, lpszFile.length + OS.MAX_PATH);
+        }
+        if (OS.ExtractIconEx (lpszFile.ptr, -1, null, null, 1) !is 0) {
+            String fileName = TCHARzToStr( lpszFile.ptr );
+            if (fileName.endsWith ("java.exe") || fileName.endsWith ("javaw.exe")) { //$NON-NLS-1$ //$NON-NLS-2$
+                lpWndClass.hIcon = OS.LoadIcon (0, OS.IDI_APPLICATION);
+            }
+        }
+    }
+    +/
     int byteCount = windowClass_.length * TCHAR.sizeof;
     lpWndClass.lpszClassName = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
     OS.MoveMemory (lpWndClass.lpszClassName, windowClass_.ptr, byteCount);
@@ -2520,7 +2595,9 @@
     OS.HeapFree (hHeap, 0, lpWndClass.lpszClassName);
 
     /* Register the DWT drop shadow window class */
-    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) lpWndClass.style |= OS.CS_DROPSHADOW;
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+        lpWndClass.style |= OS.CS_DROPSHADOW;
+    }
     byteCount = windowShadowClass.length * TCHAR.sizeof;
     lpWndClass.lpszClassName = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
     OS.MoveMemory (lpWndClass.lpszClassName, windowShadowClass.ptr, byteCount);
@@ -2540,7 +2617,7 @@
     //messageCallback = new Callback (this, "messageProc", 4); //$NON-NLS-1$
     //messageProc_ = messageCallback.getAddress ();
     //if (messageProc_ is 0) error (DWT.ERROR_NO_MORE_CALLBACKS);
-    OS.SetWindowLong (hwndMessage, OS.GWL_WNDPROC, cast(int) &messageProcFunc);
+    OS.SetWindowLongPtr (hwndMessage, OS.GWLP_WNDPROC, cast(LONG_PTR) &messageProcFunc);
 
     /* Create the filter hook */
     static if (!OS.IsWinCE) {
@@ -2561,6 +2638,7 @@
     /* Register custom messages message */
     SWT_TASKBARCREATED = OS.RegisterWindowMessage (StrToTCHARz ( "TaskbarCreated" ));
     SWT_RESTORECARET = OS.RegisterWindowMessage (StrToTCHARz ( "SWT_RESTORECARET"));
+    DI_GETDRAGIMAGE = OS.RegisterWindowMessage (StrToTCHARz ( "ShellGetDragImage")); //$NON-NLS-1$
 
     /* Initialize OLE */
     static if (!OS.IsWinCE) OS.OleInitialize (null);
@@ -2988,9 +3066,10 @@
             */
             if (wParam !is 0) {
                 if (!isXMouseActive ()) {
-                    if (modalDialogShell !is null && modalDialogShell.isDisposed ()) modalDialogShell = null;
-                    Shell modal = modalDialogShell !is null ? modalDialogShell : getModalShell ();
-                    if (modal !is null) {
+                    auto hwndActive = OS.GetActiveWindow ();
+                    if (hwndActive !is null && OS.IsWindowEnabled (hwndActive)) break;
+                    Shell modal = modalDialog !is null ? modalDialog.parent : getModalShell ();
+                    if (modal !is null && !modal.isDisposed ()) {
                         auto hwndModal = modal.handle;
                         if (OS.IsWindowEnabled (hwndModal)) {
                             modal.bringToTop ();
@@ -3017,7 +3096,8 @@
                 * to run.  In order to avoid running code after the display
                 * has been disposed, exit from Java.
                 */
-                System.exit (0);
+                /* This code is intentionally commented */
+//              System.exit (0);
             }
             break;
         }
@@ -3027,7 +3107,15 @@
             if (!event.doit) return 0;
             break;
         }
+        case OS.WM_DWMCOLORIZATIONCOLORCHANGED: {
+            OS.SetTimer (hwndMessage, SETTINGS_ID, SETTINGS_DELAY, null);
+            break;
+        }
         case OS.WM_SETTINGCHANGE: {
+            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                OS.SetTimer (hwndMessage, SETTINGS_ID, SETTINGS_DELAY, null);
+                break;
+            }
             switch (wParam) {
                 case 0:
                 case 1:
@@ -3107,9 +3195,10 @@
 int msgFilterProc (int code, int wParam, int lParam) {
     switch (code) {
         case OS.MSGF_COMMCTRL_BEGINDRAG: {
-            if (!runDragDrop) {
-                hookMsg = *cast(MSG*)lParam;
+            if (!runDragDrop && !dragCancelled) {
+                *hookMsg = *cast(MSG*)lParam;
                 if (hookMsg.message is OS.WM_MOUSEMOVE) {
+                    dragCancelled = true;
                     OS.SendMessage (hookMsg.hwnd, OS.WM_CANCELMODE, 0, 0);
                 }
             }
@@ -3131,7 +3220,7 @@
         case OS.MSGF_SCROLLBAR:
         case OS.MSGF_SIZE: {
             if (runMessages) {
-                hookMsg = *cast(MSG*)lParam;
+                *hookMsg = *cast(MSG*)lParam;
                 if (hookMsg.message is OS.WM_NULL) {
                     MSG msg;
                     int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
@@ -3224,118 +3313,120 @@
  *
  */
 public bool post (Event event) {
-    if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
-    if (event is null) error (DWT.ERROR_NULL_ARGUMENT);
-    int type = event.type;
-    switch (type){
-        case DWT.KeyDown:
-        case DWT.KeyUp: {
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
+        if (event is null) error (DWT.ERROR_NULL_ARGUMENT);
+        int type = event.type;
+        switch (type){
+            case DWT.KeyDown:
+            case DWT.KeyUp: {
             KEYBDINPUT inputs;
             inputs.wVk = cast(short) untranslateKey (event.keyCode);
-            if (inputs.wVk is 0) {
-                char key = event.character;
-                switch (key) {
-                    case DWT.BS: inputs.wVk = cast(short) OS.VK_BACK; break;
-                    case DWT.CR: inputs.wVk = cast(short) OS.VK_RETURN; break;
-                    case DWT.DEL: inputs.wVk = cast(short) OS.VK_DELETE; break;
-                    case DWT.ESC: inputs.wVk = cast(short) OS.VK_ESCAPE; break;
-                    case DWT.TAB: inputs.wVk = cast(short) OS.VK_TAB; break;
-                    /*
-                    * Since there is no LF key on the keyboard, do not attempt
-                    * to map LF to CR or attempt to post an LF key.
-                    */
-//                  case DWT.LF: inputs.wVk = cast(short) OS.VK_RETURN; break;
-                    case DWT.LF: return false;
-                    default: {
-                        static if (OS.IsWinCE) {
-                            inputs.wVk = cast(int)OS.CharUpper (cast(wchar*) key);
-                        } else {
-                            inputs.wVk = OS.VkKeyScan (cast(short) wcsToMbcs (key, 0));
-                            if (inputs.wVk is -1) return false;
-                            inputs.wVk &= 0xFF;
+                if (inputs.wVk is 0) {
+                    char key = event.character;
+                    switch (key) {
+                        case DWT.BS: inputs.wVk = cast(short) OS.VK_BACK; break;
+                        case DWT.CR: inputs.wVk = cast(short) OS.VK_RETURN; break;
+                        case DWT.DEL: inputs.wVk = cast(short) OS.VK_DELETE; break;
+                        case DWT.ESC: inputs.wVk = cast(short) OS.VK_ESCAPE; break;
+                        case DWT.TAB: inputs.wVk = cast(short) OS.VK_TAB; break;
+                        /*
+                        * Since there is no LF key on the keyboard, do not attempt
+                        * to map LF to CR or attempt to post an LF key.
+                        */
+//                      case DWT.LF: inputs.wVk = cast(short) OS.VK_RETURN; break;
+                        case DWT.LF: return false;
+                        default: {
+                            static if (OS.IsWinCE) {
+                                inputs.wVk = cast(int)OS.CharUpper (cast(wchar*) key);
+                            } else {
+                                inputs.wVk = OS.VkKeyScan (cast(short) wcsToMbcs (key, 0));
+                                if (inputs.wVk is -1) return false;
+                                inputs.wVk &= 0xFF;
+                            }
                         }
                     }
                 }
-            }
-            inputs.dwFlags = type is DWT.KeyUp ? OS.KEYEVENTF_KEYUP : 0;
+                inputs.dwFlags = type is DWT.KeyUp ? OS.KEYEVENTF_KEYUP : 0;
             auto hHeap = OS.GetProcessHeap ();
             auto pInputs = cast(INPUT*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, INPUT.sizeof);
             pInputs.type = OS.INPUT_KEYBOARD;
-            pInputs.ki = inputs;
-            //OS.MoveMemory (pInputs + 4, inputs, KEYBDINPUT.sizeof);
-            bool result = OS.SendInput (1, pInputs, INPUT.sizeof) !is 0;
-            OS.HeapFree (hHeap, 0, pInputs);
-            return result;
-        }
-        case DWT.MouseDown:
-        case DWT.MouseMove:
-        case DWT.MouseUp:
-        case DWT.MouseWheel: {
-            MOUSEINPUT inputs;
-            if (type is DWT.MouseMove){
-                inputs.dwFlags = OS.MOUSEEVENTF_MOVE | OS.MOUSEEVENTF_ABSOLUTE;
-                int x= 0, y = 0, width = 0, height = 0;
-                if (OS.WIN32_VERSION >= OS.VERSION (5, 0)) {
-                    inputs.dwFlags |= OS.MOUSEEVENTF_VIRTUALDESK;
-                    x = OS.GetSystemMetrics (OS.SM_XVIRTUALSCREEN);
-                    y = OS.GetSystemMetrics (OS.SM_YVIRTUALSCREEN);
-                    width = OS.GetSystemMetrics (OS.SM_CXVIRTUALSCREEN);
-                    height = OS.GetSystemMetrics (OS.SM_CYVIRTUALSCREEN);
+                //TODO - DWORD type of INPUT structure aligned to 8 bytes on 64 bit
+                pInputs.ki = inputs;
+                //OS.MoveMemory (pInputs + 4, inputs, KEYBDINPUT.sizeof);
+                bool result = OS.SendInput (1, pInputs, INPUT.sizeof) !is 0;
+                OS.HeapFree (hHeap, 0, pInputs);
+                return result;
+            }
+            case DWT.MouseDown:
+            case DWT.MouseMove:
+            case DWT.MouseUp:
+            case DWT.MouseWheel: {
+                MOUSEINPUT inputs;
+                if (type is DWT.MouseMove){
+                    inputs.dwFlags = OS.MOUSEEVENTF_MOVE | OS.MOUSEEVENTF_ABSOLUTE;
+                    int x= 0, y = 0, width = 0, height = 0;
+                    if (OS.WIN32_VERSION >= OS.VERSION (5, 0)) {
+                        inputs.dwFlags |= OS.MOUSEEVENTF_VIRTUALDESK;
+                        x = OS.GetSystemMetrics (OS.SM_XVIRTUALSCREEN);
+                        y = OS.GetSystemMetrics (OS.SM_YVIRTUALSCREEN);
+                        width = OS.GetSystemMetrics (OS.SM_CXVIRTUALSCREEN);
+                        height = OS.GetSystemMetrics (OS.SM_CYVIRTUALSCREEN);
+                    } else {
+                        width = OS.GetSystemMetrics (OS.SM_CXSCREEN);
+                        height = OS.GetSystemMetrics (OS.SM_CYSCREEN);
+                    }
+                    inputs.dx = ((event.x - x) * 65535 + width - 2) / (width - 1);
+                    inputs.dy = ((event.y - y) * 65535 + height - 2) / (height - 1);
                 } else {
-                    width = OS.GetSystemMetrics (OS.SM_CXSCREEN);
-                    height = OS.GetSystemMetrics (OS.SM_CYSCREEN);
-                }
-                inputs.dx = ((event.x - x) * 65535 + width - 2) / (width - 1);
-                inputs.dy = ((event.y - y) * 65535 + height - 2) / (height - 1);
-            } else {
-                if (type is DWT.MouseWheel) {
-                    if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
-                    inputs.dwFlags = OS.MOUSEEVENTF_WHEEL;
-                    switch (event.detail) {
-                        case DWT.SCROLL_PAGE:
-                            inputs.mouseData = event.count * OS.WHEEL_DELTA;
-                            break;
-                        case DWT.SCROLL_LINE:
-                            int value;
-                            OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, &value, 0);
-                            inputs.mouseData = event.count * OS.WHEEL_DELTA / value;
-                            break;
-                        default: return false;
-                    }
-                } else {
-                    switch (event.button) {
-                        case 1: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_LEFTDOWN : OS.MOUSEEVENTF_LEFTUP; break;
-                        case 2: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_MIDDLEDOWN : OS.MOUSEEVENTF_MIDDLEUP; break;
-                        case 3: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_RIGHTDOWN : OS.MOUSEEVENTF_RIGHTUP; break;
-                        case 4: {
-                            if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
-                            inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP;
-                            inputs.mouseData = OS.XBUTTON1;
-                            break;
+                    if (type is DWT.MouseWheel) {
+                        if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
+                        inputs.dwFlags = OS.MOUSEEVENTF_WHEEL;
+                        switch (event.detail) {
+                            case DWT.SCROLL_PAGE:
+                                inputs.mouseData = event.count * OS.WHEEL_DELTA;
+                                break;
+                            case DWT.SCROLL_LINE:
+                                int value;
+                                OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, &value, 0);
+                                inputs.mouseData = event.count * OS.WHEEL_DELTA / value;
+                                break;
+                            default: return false;
                         }
-                        case 5: {
-                            if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
-                            inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP;
-                            inputs.mouseData = OS.XBUTTON2;
-                            break;
+                    } else {
+                        switch (event.button) {
+                            case 1: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_LEFTDOWN : OS.MOUSEEVENTF_LEFTUP; break;
+                            case 2: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_MIDDLEDOWN : OS.MOUSEEVENTF_MIDDLEUP; break;
+                            case 3: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_RIGHTDOWN : OS.MOUSEEVENTF_RIGHTUP; break;
+                            case 4: {
+                                if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
+                                inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP;
+                                inputs.mouseData = OS.XBUTTON1;
+                                break;
+                            }
+                            case 5: {
+                                if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
+                                inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP;
+                                inputs.mouseData = OS.XBUTTON2;
+                                break;
+                            }
+                            default: return false;
                         }
-                        default: return false;
                     }
                 }
+                auto hHeap = OS.GetProcessHeap ();
+                auto pInputs = cast(INPUT*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, INPUT.sizeof);
+                pInputs.type = OS.INPUT_MOUSE;
+                //TODO - DWORD type of INPUT structure aligned to 8 bytes on 64 bit
+                pInputs.mi = inputs;
+                bool result = OS.SendInput (1, pInputs, INPUT.sizeof) !is 0;
+                OS.HeapFree (hHeap, 0, pInputs);
+                return result;
             }
-            auto hHeap = OS.GetProcessHeap ();
-            auto pInputs = cast(INPUT*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, INPUT.sizeof);
-            pInputs.type = OS.INPUT_MOUSE;
-            //OS.MoveMemory(pInputs, [OS.INPUT_MOUSE], 4);
-            pInputs.mi = inputs;
-            //OS.MoveMemory (pInputs + 4, inputs, MOUSEINPUT.sizeof);
-            bool result = OS.SendInput (1, pInputs, INPUT.sizeof) !is 0;
-            OS.HeapFree (hHeap, 0, pInputs);
-            return result;
+        default:
         }
-        default:
+        return false;
     }
-    return false;
 }
 
 void postEvent (Event event) {
@@ -3389,10 +3480,10 @@
     lpStartupInfo = null;
     drawMenuBars ();
     runPopups ();
-    if (OS.PeekMessage (&msg, null, 0, 0, OS.PM_REMOVE)) {
-        if (!filterMessage (&msg)) {
-            OS.TranslateMessage (&msg);
-            OS.DispatchMessage (&msg);
+    if (OS.PeekMessage (msg, null, 0, 0, OS.PM_REMOVE)) {
+        if (!filterMessage (msg)) {
+            OS.TranslateMessage (msg);
+            OS.DispatchMessage (msg);
         }
         runDeferredEvents ();
         return true;
@@ -3400,18 +3491,20 @@
     return runMessages && runAsyncMessages (false);
 }
 
-static synchronized void register (Display display) {
+static void register (Display display) {
     static_this();
-    for (int i=0; i<Displays.length; i++) {
-        if (Displays [i] is null) {
-            Displays [i] = display;
-            return;
+    synchronized (Device.classinfo) {
+        for (int i=0; i<Displays.length; i++) {
+            if (Displays [i] is null) {
+                Displays [i] = display;
+                return;
+            }
         }
+        Display [] newDisplays = new Display [Displays.length + 4];
+        System.arraycopy (Displays, 0, newDisplays, 0, Displays.length);
+        newDisplays [Displays.length] = display;
+        Displays = newDisplays;
     }
-    Display [] newDisplays = new Display [Displays.length + 4];
-    System.arraycopy (Displays, 0, newDisplays, 0, Displays.length);
-    newDisplays [Displays.length] = display;
-    Displays = newDisplays;
 }
 
 /**
@@ -3563,18 +3656,31 @@
 
     /* Release references */
     thread = null;
-    //msg = null;
+    msg = null;
+    hookMsg = null;
     //keyboard = null;
-    modalDialogShell = null;
+    modalDialog = null;
     modalShells = null;
     data = null;
     keys = null;
     values = null;
     bars = popups = null;
     indexTable = null;
+    timerIds = null;
     controlTable = null;
     lastControl = lastGetControl = lastHittestControl = null;
     imageList = toolImageList = toolHotImageList = toolDisabledImageList = null;
+    timerList = null;
+    tableBuffer = null;
+    columnVisible = null;
+    eventTable = filterTable = null;
+    items = null;
+    clickRect = null;
+    hdr = null;
+    plvfi = null;
+
+    /* Release handles */
+    threadId = 0;
 }
 
 void releaseImageList (ImageList list) {
@@ -3731,16 +3837,14 @@
     static if (USE_PROPERTY) {
         index = cast(int)OS.RemoveProp (handle, cast(wchar*)SWT_OBJECT_INDEX) - 1;
     } else {
-        index = OS.GetWindowLong (handle, OS.GWL_USERDATA) - 1;
+        index = OS.GetWindowLongPtr (handle, OS.GWLP_USERDATA) - 1;
+        OS.SetWindowLongPtr (handle, OS.GWLP_USERDATA, 0);
     }
     if (0 <= index && index < controlTable.length) {
         control = controlTable [index];
         controlTable [index] = null;
         indexTable [index] = freeSlot;
         freeSlot = index;
-        if (!USE_PROPERTY) {
-            OS.SetWindowLong (handle, OS.GWL_USERDATA, 0);
-        }
     }
     return control;
 }
@@ -3838,7 +3942,7 @@
     }
 }
 
-bool runTimer (int id) {
+bool runTimer (int /*long*/ id) {
     if (timerList !is null && timerIds !is null) {
         int index = 0;
         while (index <timerIds.length) {
@@ -3999,6 +4103,11 @@
         runMessagesInIdle = data !is null && data.value;
         return;
     }
+    if (key.equals (RUN_MESSAGES_IN_MESSAGE_PROC_KEY)) {
+        Boolean data = cast(Boolean) value;
+        runMessagesInMessageProc = data !is null && data.booleanValue ();
+        return;
+    }
 
     /* Remove the key/value pair */
     if (value is null) {
@@ -4086,9 +4195,8 @@
     /* Do nothing */
 }
 
-void setModalDialogShell (Shell modalDailog) {
-    if (modalDialogShell !is null && modalDialogShell.isDisposed ()) modalDialogShell = null;
-    this.modalDialogShell = modalDailog;
+void setModalDialog (Dialog modalDailog) {
+    this.modalDialog = modalDailog;
     Shell [] shells = getShells ();
     for (int i=0; i<shells.length; i++) shells [i].updateModal ();
 }
@@ -4129,10 +4237,15 @@
 public void setSynchronizer (Synchronizer synchronizer) {
     checkDevice ();
     if (synchronizer is null) error (DWT.ERROR_NULL_ARGUMENT);
-    if (this.synchronizer !is null) {
-        this.synchronizer.runAsyncMessages(true);
+    if (synchronizer is this.synchronizer) return;
+    Synchronizer oldSynchronizer;
+    synchronized (Device.classinfo) {
+        oldSynchronizer = this.synchronizer;
+        this.synchronizer = synchronizer;
     }
-    this.synchronizer = synchronizer;
+    if (oldSynchronizer !is null) {
+        oldSynchronizer.runAsyncMessages(true);
+    }
 }
 
 int shiftedKey (int key) {
@@ -4200,7 +4313,11 @@
  * @see #asyncExec
  */
 public void syncExec (Runnable runnable) {
-    if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
+    Synchronizer synchronizer;
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
+        synchronizer = this.synchronizer;
+    }
     synchronizer.syncExec (runnable);
 }
 
@@ -4234,13 +4351,13 @@
     if (runnable is null) error (DWT.ERROR_NULL_ARGUMENT);
     assert( runnable );
     if (timerList is null) timerList = new Runnable [4];
-    if (timerIds is null) timerIds = new int [4];
+    if (timerIds is null) timerIds = new int /*long*/ [4];
     int index = 0;
     while (index < timerList.length) {
         if (timerList [index] is runnable) break;
         index++;
     }
-    int timerId = 0;
+    int /*long*/ timerId = 0;
     if (index !is timerList.length) {
         timerId = timerIds [index];
         if (milliseconds < 0) {
@@ -4261,7 +4378,7 @@
             Runnable [] newTimerList = new Runnable [timerList.length + 4];
             SimpleType!(Runnable).arraycopy (timerList, 0, newTimerList, 0, timerList.length);
             timerList = newTimerList;
-            int [] newTimerIds = new int [timerIds.length + 4];
+            int /*long*/ [] newTimerIds = new int /*long*/ [timerIds.length + 4];
             System.arraycopy (timerIds, 0, newTimerIds, 0, timerIds.length);
             timerIds = newTimerIds;
         }
@@ -4395,9 +4512,11 @@
  * @see #sleep
  */
 public void wake () {
-    if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
-    if (thread is Thread.getThis ()) return;
-    wakeThread ();
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
+        if (thread is Thread.getThis ()) return;
+        wakeThread ();
+    }
 }
 
 void wakeThread () {
@@ -4451,6 +4570,27 @@
 
 int windowProc (HWND hwnd, uint msg, uint wParam, int lParam) {
     /*
+    * Feature in Windows.  On Vista only, it is faster to
+    * compute and answer the data for the visible columns
+    * of a table when scrolling, rather than just return
+    * the data for each column when asked.
+    */
+    if (columnVisible !is null) {
+        if (msg is OS.WM_NOTIFY && hwndParent is hwnd) {
+            OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
+            switch (hdr.code) {
+                case OS.LVN_GETDISPINFOA:
+                case OS.LVN_GETDISPINFOW: {
+                    OS.MoveMemory (plvfi, lParam, NMLVDISPINFO.sizeof);
+                    if (0 <= plvfi.item.iSubItem && plvfi.item.iSubItem < columnCount) {
+                        if (!columnVisible [plvfi.item.iSubItem]) return 0;
+                    }
+                    break;
+                }
+            }
+        }
+    }
+    /*
     * Bug in Adobe Reader 7.0.  For some reason, when Adobe
     * Reader 7.0 is deactivated from within Internet Explorer,
     * it sends thousands of consecutive WM_NCHITTEST messages
@@ -4477,7 +4617,7 @@
     static if (USE_PROPERTY) {
         index = cast(int)OS.GetProp (hwnd, cast(wchar*)SWT_OBJECT_INDEX) - 1;
     } else {
-        index = OS.GetWindowLong (hwnd, OS.GWL_USERDATA) - 1;
+        index = OS.GetWindowLongPtr (hwnd, OS.GWLP_USERDATA) - 1;
     }
     if (0 <= index && index < controlTable.length) {
         Control control = controlTable [index];