Fix for win32 GtkTreeView DnD bug



Herman Bloggs writes:
 > 1) In gdk_drag_find_window_for_screen the call to WindowFromPoint would
 > consistantly return the handle to the DnD pointer icon window (created
 > by gtk_drag_set_icon_pixmap), instead of the DnD target window
 > underneath. The solution (not a good one) is to offset the pointer icon
 > window 1 pixel from the pointer position (in the call to
 > gtk_drag_set_icon_pixmap), so that the pointer position won't be within
 > the bounds of the DnD pointer icon window when the call to
 > WindowFromPoint is made.

A better solution is included below. It uses EnumWindows() instead of
WindowFromPoint() to find the correct window. Seems to work fine, dnd
in testtreeview seems to work OK. (I can't compare now to how it works
on X11, though, so not 100% sure.)

 > Still not working: When both GDK_ACTION_MOVE and GDK_ACTION_COPY
 > DnD operations are permitted, holding down the ctrl key will not
 > enable the copy action.

Didn't look into that yet.

--tml

Index: gdk/win32/gdkdnd-win32.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/win32/gdkdnd-win32.c,v
retrieving revision 1.33
diff -u -2 -r1.33 gdkdnd-win32.c
--- gdk/win32/gdkdnd-win32.c	12 Nov 2002 22:17:37 -0000	1.33
+++ gdk/win32/gdkdnd-win32.c	29 Jun 2003 03:04:40 -0000
@@ -1318,4 +1312,41 @@
 }
 
+typedef struct {
+  gint x;
+  gint y;
+  HWND ignore;
+  HWND result;
+} find_window_enum_arg;
+
+static BOOL CALLBACK
+find_window_enum_proc (HWND   hwnd,
+		       LPARAM lparam)
+{
+  RECT rect;
+  POINT tl, br;
+  find_window_enum_arg *a = (find_window_enum_arg *) lparam;
+
+  if (hwnd == a->ignore)
+    return TRUE;
+
+  if (!IsWindowVisible (hwnd))
+    return TRUE;
+
+  tl.x = tl.y = 0;
+  ClientToScreen (hwnd, &tl);
+  GetClientRect (hwnd, &rect);
+  br.x = rect.right;
+  br.y = rect.bottom;
+  ClientToScreen (hwnd, &br);
+
+  if (a->x >= tl.x && a->y >= tl.y && a->x < br.x && a->y < br.y)
+    {
+      a->result = hwnd;
+      return FALSE;
+    }
+  else
+    return TRUE;
+}
+
 void
 gdk_drag_find_window_for_screen (GdkDragContext  *context,
@@ -1327,19 +1358,22 @@
 				 GdkDragProtocol *protocol)
 {
-  HWND recipient;
-  POINT pt;
+  find_window_enum_arg a;
+
+  a.x = x_root;
+  a.y = y_root;
+  a.ignore = drag_window ? GDK_WINDOW_HWND (drag_window) : NULL;
+  a.result = NULL;
 
-  pt.x = x_root;
-  pt.y = y_root;
-  recipient = WindowFromPoint (pt);
-  if (recipient == NULL)
+  EnumWindows (find_window_enum_proc, (LPARAM) &a);
+
+  if (a.result == NULL)
     *dest_window = NULL;
   else
     {
-      *dest_window = gdk_win32_handle_table_lookup (GPOINTER_TO_UINT(recipient));
+      *dest_window = gdk_win32_handle_table_lookup (GPOINTER_TO_UINT (a.result));
       if (*dest_window)
 	{
 	  *dest_window = gdk_window_get_toplevel (*dest_window);
-	  gdk_drawable_ref (*dest_window);
+	  g_object_ref (*dest_window);
 	}
 
@@ -1350,7 +1384,11 @@
     }
 
-  GDK_NOTE (DND, g_print ("gdk_drag_find_window: %#x +%d+%d Protocol: %d\n",
-			  (drag_window ? (guint) GDK_WINDOW_HWND (drag_window) : 0),
-			  x_root, y_root, *protocol));
+  GDK_NOTE (DND,
+	    g_print ("gdk_drag_find_window: %p +%d+%d: %p: %p %d\n",
+		     (drag_window ? GDK_WINDOW_HWND (drag_window) : NULL),
+		     x_root, y_root,
+		     a.result,
+		     (*dest_window ? GDK_WINDOW_HWND (*dest_window) : NULL),
+		     *protocol));
 }
 
@@ -1508,4 +1546,6 @@
   private = GDK_DRAG_CONTEXT_PRIVATE_DATA (context);
 
+  context->action = action;
+
   src_context = gdk_drag_context_find (TRUE,
 				       context->source_window,





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]