diff dwt/dnd/DragSource.d @ 194:3afcd4ddcf90

Update to SWT 3.3.2
author Frank Benoit <benoit@tionex.de>
date Wed, 19 Mar 2008 21:48:31 +0100
parents 04e357b8343d
children ab60f3309436
line wrap: on
line diff
--- a/dwt/dnd/DragSource.d	Mon Mar 17 21:47:05 2008 +0100
+++ b/dwt/dnd/DragSource.d	Wed Mar 19 21:48:31 2008 +0100
@@ -131,6 +131,7 @@
     Transfer[] transferAgents;
     DragSourceEffect dragEffect;
     Composite topControl;
+    HWND hwndDrag;
 
     // ole interfaces
     _IDropSourceImpl iDropSource;
@@ -143,6 +144,7 @@
     static const char[] DEFAULT_DRAG_SOURCE_EFFECT = "DEFAULT_DRAG_SOURCE_EFFECT"; //$NON-NLS-1$
     static const char[] DRAGSOURCEID = "DragSource"; //$NON-NLS-1$
     static const int CFSTR_PERFORMEDDROPEFFECT;
+    static final TCHAR[] WindowClass = "#32770\0";
     static this(){
         CFSTR_PERFORMEDDROPEFFECT  = Transfer.registerType("Performed DropEffect");     //$NON-NLS-1$
     }
@@ -298,17 +300,43 @@
     uint[1] pdwEffect;
     int operations = opToOs(getStyle());
     Display display = control.getDisplay();
-    char[] key = "org.eclipse.swt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$
+    char[] key = "dwt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$
     Object oldValue = display.getData(key);
     display.setData(key, new ValueWrapperBool(true));
     ImageList imagelist = null;
     Image image = event.image;
+    hwndDrag = null;
+    topControl = null;
     if (image !is null) {
         imagelist = new ImageList(DWT.NONE);
         imagelist.add(image);
         topControl = control.getShell();
-        OS.ImageList_BeginDrag(imagelist.getHandle(), 0, 0, 0);
-        Point location = topControl.getLocation();
+        /*
+         * Bug in Windows. The image is inverted if the shell is RIGHT_TO_LEFT.
+         * The fix is to create a transparent window that covers the shell client
+         * area and use it during the drag to prevent the image from being inverted.
+         * On XP if the shell is RTL, the image is not displayed.
+         */
+        int offset = 0;
+        hwndDrag = topControl.handle;
+        if ((topControl.getStyle() & DWT.RIGHT_TO_LEFT) !is 0) {
+            offset = image.getBounds().width;
+            RECT rect;
+            OS.GetClientRect (topControl.handle, &rect);
+            hwndDrag = OS.CreateWindowEx (
+                OS.WS_EX_TRANSPARENT | OS.WS_EX_NOINHERITLAYOUT,
+                WindowClass.ptr,
+                null,
+                OS.WS_CHILD | OS.WS_CLIPSIBLINGS,
+                0, 0,
+                rect.right - rect.left, rect.bottom - rect.top,
+                topControl.handle,
+                null,
+                OS.GetModuleHandle (null),
+                null);
+            OS.ShowWindow (hwndDrag, OS.SW_SHOW);
+        }
+        OS.ImageList_BeginDrag(imagelist.getHandle(), 0, offset, 0);
         /*
         * Feature in Windows. When ImageList_DragEnter() is called,
         * it takes a snapshot of the screen  If a drag is started
@@ -323,16 +351,29 @@
             int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
             OS.RedrawWindow (topControl.handle, null, null, flags);
         }
-        OS.ImageList_DragEnter(topControl.handle, dragEvent.x - location.x, dragEvent.y - location.y);
+        POINT pt;
+        pt.x = dragEvent.x;
+        pt.y = dragEvent.y;
+        OS.MapWindowPoints (control.handle, null, &pt, 1);
+        RECT rect;
+        OS.GetWindowRect (hwndDrag, &rect);
+        OS.ImageList_DragEnter(hwndDrag, pt.x - rect.left, pt.y - rect.top);
     }
-    int result = COM.DoDragDrop(iDataObject, iDropSource, operations, pdwEffect.ptr);
-    if (imagelist !is null) {
-        OS.ImageList_DragLeave(topControl.handle);
-        OS.ImageList_EndDrag();
-        imagelist.dispose();
-        topControl = null;
+    int result = COM.DRAGDROP_S_CANCEL;
+    try {
+        result = COM.DoDragDrop(iDataObject, iDropSource, operations, pdwEffect.ptr);
+    } finally {
+        // ensure that we don't leave transparent window around
+        if (hwndDrag !is null) {
+            OS.ImageList_DragLeave(hwndDrag);
+            OS.ImageList_EndDrag();
+            imagelist.dispose();
+            if (hwndDrag !is topControl.handle) OS.DestroyWindow(hwndDrag);
+            hwndDrag = null;
+            topControl = null;
+        }
+        display.setData(key, oldValue);
     }
-    display.setData(key, oldValue);
     int operation = osToOp(pdwEffect[0]);
     if (dataEffect is DND.DROP_MOVE) {
         operation = (operation is DND.DROP_NONE || operation is DND.DROP_COPY) ? DND.DROP_TARGET_MOVE : DND.DROP_MOVE;
@@ -459,8 +500,9 @@
 }
 
 package .LRESULT QueryContinueDrag(int fEscapePressed, DWORD grfKeyState) {
+    if (topControl !is null && topControl.isDisposed()) return COM.DRAGDROP_S_CANCEL;
     if (fEscapePressed !is 0){
-        if (topControl !is null) OS.ImageList_DragLeave(topControl.handle);
+        if (hwndDrag !is null) OS.ImageList_DragLeave(hwndDrag);
         return COM.DRAGDROP_S_CANCEL;
     }
     /*
@@ -472,15 +514,16 @@
     int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON;
 //  if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
     if ((grfKeyState & mask) is 0) {
-        if (topControl !is null) OS.ImageList_DragLeave(topControl.handle);
+        if (hwndDrag !is null) OS.ImageList_DragLeave(hwndDrag);
         return COM.DRAGDROP_S_DROP;
     }
 
-    if (topControl !is null) {
-        Display display = getDisplay();
-        Point pt = display.getCursorLocation();
-        Point location = topControl.getLocation();
-        OS.ImageList_DragMove(pt.x - location.x, pt.y - location.y);
+    if (hwndDrag !is null) {
+        POINT pt;
+        OS.GetCursorPos (&pt);
+        RECT rect;
+        OS.GetWindowRect (hwndDrag, &rect);
+        OS.ImageList_DragMove (pt.x - rect.left, pt.y - rect.top);
     }
     return COM.S_OK;
 }