Skip to content

Commit 8c7de99

Browse files
author
Atterpac
committed
Fix windows dnd
1 parent e040e07 commit 8c7de99

3 files changed

Lines changed: 231 additions & 20 deletions

File tree

v3/examples/drag-n-drop/assets/index.html

Lines changed: 131 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,95 @@ <h2 class="info-header">Drop Information</h2>
252252
const pathDisplay = document.getElementById('current-path');
253253
const folderNodes = document.querySelectorAll('.folder-dropzone');
254254

255+
// Add debug coordinate overlay
256+
let debugOverlay = null;
257+
258+
function createDebugOverlay() {
259+
if (debugOverlay) return;
260+
261+
debugOverlay = document.createElement('div');
262+
debugOverlay.style.cssText = `
263+
position: fixed;
264+
top: 10px;
265+
right: 10px;
266+
background: rgba(0, 0, 0, 0.8);
267+
color: white;
268+
padding: 10px;
269+
border-radius: 5px;
270+
font-family: monospace;
271+
font-size: 12px;
272+
z-index: 10000;
273+
pointer-events: none;
274+
white-space: pre-line;
275+
`;
276+
document.body.appendChild(debugOverlay);
277+
}
278+
279+
function updateDebugOverlay(info) {
280+
if (!debugOverlay) createDebugOverlay();
281+
debugOverlay.textContent = info;
282+
}
283+
284+
// Track mouse position and other debug info
285+
let mouseInfo = { x: 0, y: 0 };
286+
let windowInfo = { width: window.innerWidth, height: window.innerHeight };
287+
288+
document.addEventListener('mousemove', (e) => {
289+
mouseInfo.x = e.clientX;
290+
mouseInfo.y = e.clientY;
291+
292+
const debugInfo = `Mouse: ${e.clientX}, ${e.clientY}
293+
Page: ${e.pageX}, ${e.pageY}
294+
Screen: ${e.screenX}, ${e.screenY}
295+
Window: ${windowInfo.width}x${windowInfo.height}
296+
Viewport offset: ${window.pageXOffset}, ${window.pageYOffset}`;
297+
298+
updateDebugOverlay(debugInfo);
299+
});
300+
301+
// Add drag event listeners to show coordinates during drag
302+
document.addEventListener('dragover', (e) => {
303+
e.preventDefault();
304+
const debugInfo = `[DRAGOVER]
305+
Mouse: ${e.clientX}, ${e.clientY}
306+
Page: ${e.pageX}, ${e.pageY}
307+
Screen: ${e.screenX}, ${e.screenY}
308+
Window: ${windowInfo.width}x${windowInfo.height}
309+
Target: ${e.target.tagName} ${e.target.className}`;
310+
311+
updateDebugOverlay(debugInfo);
312+
});
313+
314+
document.addEventListener('drop', (e) => {
315+
e.preventDefault();
316+
const rect = e.target.getBoundingClientRect();
317+
const debugInfo = `[DROP EVENT]
318+
Client: ${e.clientX}, ${e.clientY}
319+
Page: ${e.pageX}, ${e.pageY}
320+
Screen: ${e.screenX}, ${e.screenY}
321+
Target rect: ${rect.left}, ${rect.top}, ${rect.width}x${rect.height}
322+
Relative to target: ${e.clientX - rect.left}, ${e.clientY - rect.top}
323+
Window: ${windowInfo.width}x${windowInfo.height}`;
324+
325+
updateDebugOverlay(debugInfo);
326+
console.log('Drop event debug info:', {
327+
clientX: e.clientX,
328+
clientY: e.clientY,
329+
pageX: e.pageX,
330+
pageY: e.pageY,
331+
screenX: e.screenX,
332+
screenY: e.screenY,
333+
targetRect: rect,
334+
relativeX: e.clientX - rect.left,
335+
relativeY: e.clientY - rect.top
336+
});
337+
});
338+
339+
window.addEventListener('resize', () => {
340+
windowInfo.width = window.innerWidth;
341+
windowInfo.height = window.innerHeight;
342+
});
343+
255344
// Update path display when clicking folders
256345
folderNodes.forEach(folder => {
257346
folder.addEventListener('click', (e) => {
@@ -266,43 +355,70 @@ <h2 class="info-header">Drop Information</h2>
266355

267356
// Listen for the file drop event from Wails
268357
wails.Events.On("frontend:FileDropInfo", (eventData) => {
269-
console.log("File drop detected:", eventData);
358+
console.log("=============== Frontend: File Drop Debug Info ===============");
359+
console.log("Full event data:", eventData);
270360

271361
const { files, targetID, targetClasses, dropX, dropY, attributes } = eventData.data[0];
272362

363+
console.log("Extracted data:", {
364+
files,
365+
targetID,
366+
targetClasses,
367+
dropX,
368+
dropY,
369+
attributes
370+
});
371+
273372
// Get additional folder information from the attributes
274373
const folderPath = attributes ? attributes['data-path'] : 'Unknown path';
275374
const folderName = attributes ? attributes['data-folder-name'] : 'Unknown folder';
276375

277-
let message = `Files dropped on folder: ${folderName}\n`;
376+
let message = `=============== FILE DROP DEBUG REPORT ===============\n`;
377+
message += `Files dropped on folder: ${folderName}\n`;
278378
message += `Target path: ${folderPath}\n`;
279379
message += `Element ID: ${targetID || 'N/A'}\n`;
280-
message += `Element Classes: ${targetClasses && targetClasses.length > 0 ? targetClasses.join(', ') : 'N/A'}\n\n`;
380+
message += `Element Classes: ${targetClasses && targetClasses.length > 0 ? targetClasses.join(', ') : 'N/A'}\n`;
381+
message += `\n=== COORDINATE DEBUG INFO ===\n`;
382+
message += `Drop Coordinates from Wails: X=${dropX.toFixed(2)}, Y=${dropY.toFixed(2)}\n`;
383+
message += `Current Mouse Position: X=${mouseInfo.x}, Y=${mouseInfo.y}\n`;
384+
message += `Window Size: ${windowInfo.width}x${windowInfo.height}\n`;
385+
386+
// Get the target element to show its position
387+
const targetElement = document.querySelector(`[data-folder-id="${targetID}"]`);
388+
if (targetElement) {
389+
const rect = targetElement.getBoundingClientRect();
390+
message += `Target Element Position:\n`;
391+
message += ` - Bounding rect: left=${rect.left}, top=${rect.top}, right=${rect.right}, bottom=${rect.bottom}\n`;
392+
message += ` - Size: ${rect.width}x${rect.height}\n`;
393+
message += ` - Center: ${rect.left + rect.width/2}, ${rect.top + rect.height/2}\n`;
394+
message += ` - Drop relative to element: X=${dropX - rect.left}, Y=${dropY - rect.top}\n`;
395+
}
281396

282-
// Display all attributes from the element
397+
message += `\n=== ELEMENT ATTRIBUTES ===\n`;
283398
if (attributes && Object.keys(attributes).length > 0) {
284-
message += "Element Attributes:\n";
285399
Object.entries(attributes).forEach(([key, value]) => {
286400
message += ` ${key}: "${value}"\n`;
287401
});
288-
message += "\n";
402+
} else {
403+
message += " No attributes found\n";
289404
}
290405

291-
// List all dropped files
292-
message += "Dropped Files:\n";
293-
files.forEach(file => {
294-
message += ` → ${file}\n`;
406+
message += `\n=== DROPPED FILES ===\n`;
407+
files.forEach((file, index) => {
408+
message += ` ${index + 1}. ${file}\n`;
295409
});
296410

297-
message += `\nDrop Coordinates: X=${dropX.toFixed(2)}, Y=${dropY.toFixed(2)}`;
298-
299-
// Show a simulated upload message
300-
message += "\n\nSimulating upload to " + folderPath + "...";
411+
message += `\n=== SIMULATION ===\n`;
412+
message += `Simulating upload to ${folderPath}...\n`;
413+
message += `===========================================`;
301414

302415
outputDiv.textContent = message;
416+
417+
console.log("=============== End Frontend Debug ===============");
303418
});
304419

305-
console.log("File Tree Drag-and-Drop example initialized.");
420+
console.log("File Tree Drag-and-Drop example initialized with enhanced debugging.");
421+
createDebugOverlay();
306422
</script>
307423
</body>
308424
</html>

v3/examples/drag-n-drop/main.go

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,24 @@ func FilesDroppedOnTarget(
5151
dropX float64,
5252
dropY float64,
5353
isTargetDropzone bool, // This parameter is kept for logging but not sent to frontend in this event
54+
attributes map[string]string,
5455
) {
55-
log.Println("Go: FilesDroppedOnTarget method called")
56+
log.Println("=============== Go: FilesDroppedOnTarget Debug Info ===============")
5657
log.Println(fmt.Sprintf(" Files: %v", files))
5758
log.Println(fmt.Sprintf(" Target ID: '%s'", targetID))
5859
log.Println(fmt.Sprintf(" Target Classes: %v", targetClasses))
5960
log.Println(fmt.Sprintf(" Drop X: %f, Drop Y: %f", dropX, dropY))
6061
log.Println(fmt.Sprintf(" Drop occurred on a designated dropzone (runtime validated before this Go event): %t", isTargetDropzone))
62+
log.Println(fmt.Sprintf(" Element Attributes: %v", attributes))
63+
log.Println("================================================================")
6164

6265
payload := FileDropInfo{
6366
Files: files,
6467
TargetID: targetID,
6568
TargetClasses: targetClasses,
6669
DropX: dropX,
6770
DropY: dropY,
71+
Attributes: attributes,
6872
}
6973

7074
log.Println("Go: Emitted 'frontend:FileDropInfo' event with payload:", payload)
@@ -101,22 +105,36 @@ func main() {
101105
win.OnWindowEvent(
102106
events.Common.WindowDropZoneFilesDropped,
103107
func(event *application.WindowEvent) {
108+
log.Println("=============== WindowDropZoneFilesDropped Event Debug ===============")
109+
104110
droppedFiles := event.Context().DroppedFiles()
105111
details := event.Context().DropZoneDetails()
106-
// Call the App method with the extracted data
112+
113+
log.Printf("Dropped files count: %d", len(droppedFiles))
114+
log.Printf("Event context: %+v", event.Context())
115+
107116
if details != nil {
117+
log.Printf("DropZone details found:")
118+
log.Printf(" ElementID: '%s'", details.ElementID)
119+
log.Printf(" ClassList: %v", details.ClassList)
120+
log.Printf(" X: %d, Y: %d", details.X, details.Y)
121+
log.Printf(" Attributes: %+v", details.Attributes)
122+
123+
// Call the App method with the extracted data
108124
FilesDroppedOnTarget(
109125
droppedFiles,
110126
details.ElementID,
111127
details.ClassList,
112128
float64(details.X),
113129
float64(details.Y),
114130
details.ElementID != "", // isTargetDropzone based on whether an ID was found
131+
details.Attributes,
115132
)
116133
} else {
134+
log.Println("DropZone details are nil - drop was not on a specific registered zone")
117135
// This case might occur if DropZoneDetails are nil, meaning the drop was not on a specific registered zone
118136
// or if the context itself was problematic.
119-
FilesDroppedOnTarget(droppedFiles, "", nil, 0, 0, false)
137+
FilesDroppedOnTarget(droppedFiles, "", nil, 0, 0, false, nil)
120138
}
121139

122140
payload := FileDropInfo{
@@ -127,7 +145,10 @@ func main() {
127145
DropY: float64(details.Y),
128146
Attributes: details.Attributes, // Add the attributes
129147
}
148+
149+
log.Printf("Emitting event payload: %+v", payload)
130150
application.Get().EmitEvent("frontend:FileDropInfo", payload)
151+
log.Println("=============== End WindowDropZoneFilesDropped Event Debug ===============")
131152
},
132153
)
133154

v3/pkg/application/webview_window_windows.go

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,59 @@ func (w *windowsWebviewWindow) getBorderSizes() *LRTB {
513513
return &result
514514
}
515515

516+
// convertWindowToWebviewCoordinates converts window-relative coordinates to webview-relative coordinates
517+
func (w *windowsWebviewWindow) convertWindowToWebviewCoordinates(windowX, windowY int) (int, int) {
518+
// Get the client area of the window (this excludes borders, title bar, etc.)
519+
clientRect := w32.GetClientRect(w.hwnd)
520+
if clientRect == nil {
521+
// Fallback: return coordinates as-is if we can't get client rect
522+
fmt.Printf("[DragDropDebug] convertWindowToWebviewCoordinates: Failed to get client rect, returning original coordinates (%d, %d)\n", windowX, windowY)
523+
return windowX, windowY
524+
}
525+
526+
// Get the window rect to calculate the offset
527+
windowRect := w32.GetWindowRect(w.hwnd)
528+
529+
fmt.Printf("[DragDropDebug] convertWindowToWebviewCoordinates: Input window coordinates: (%d, %d)\n", windowX, windowY)
530+
fmt.Printf("[DragDropDebug] convertWindowToWebviewCoordinates: Window rect: Left=%d, Top=%d, Right=%d, Bottom=%d (Size: %dx%d)\n",
531+
windowRect.Left, windowRect.Top, windowRect.Right, windowRect.Bottom,
532+
windowRect.Right-windowRect.Left, windowRect.Bottom-windowRect.Top)
533+
fmt.Printf("[DragDropDebug] convertWindowToWebviewCoordinates: Client rect: Left=%d, Top=%d, Right=%d, Bottom=%d (Size: %dx%d)\n",
534+
clientRect.Left, clientRect.Top, clientRect.Right, clientRect.Bottom,
535+
clientRect.Right-clientRect.Left, clientRect.Bottom-clientRect.Top)
536+
537+
// Convert client (0,0) to screen coordinates to find where the client area starts
538+
var point w32.POINT
539+
point.X = 0
540+
point.Y = 0
541+
542+
// Convert client (0,0) to screen coordinates
543+
clientX, clientY := w32.ClientToScreen(w.hwnd, int(point.X), int(point.Y))
544+
545+
// The window coordinates from drag drop are relative to the window's top-left
546+
// But we need them relative to the client area's top-left
547+
// So we need to subtract the difference between window origin and client origin
548+
windowOriginX := int(windowRect.Left)
549+
windowOriginY := int(windowRect.Top)
550+
551+
fmt.Printf("[DragDropDebug] convertWindowToWebviewCoordinates: Client (0,0) in screen coordinates: (%d, %d)\n", clientX, clientY)
552+
fmt.Printf("[DragDropDebug] convertWindowToWebviewCoordinates: Window origin in screen coordinates: (%d, %d)\n", windowOriginX, windowOriginY)
553+
554+
// Calculate the offset from window origin to client origin
555+
offsetX := clientX - windowOriginX
556+
offsetY := clientY - windowOriginY
557+
558+
fmt.Printf("[DragDropDebug] convertWindowToWebviewCoordinates: Calculated offset: (%d, %d)\n", offsetX, offsetY)
559+
560+
// Convert window-relative coordinates to webview-relative coordinates
561+
webviewX := windowX - offsetX
562+
webviewY := windowY - offsetY
563+
564+
fmt.Printf("[DragDropDebug] convertWindowToWebviewCoordinates: Final webview coordinates: (%d, %d)\n", webviewX, webviewY)
565+
566+
return webviewX, webviewY
567+
}
568+
516569
func (w *windowsWebviewWindow) physicalBounds() Rect {
517570
// var rect w32.RECT
518571
// // Get the extended frame bounds instead of the window rect to offset the invisible borders in Windows 10
@@ -1699,7 +1752,20 @@ func (w *windowsWebviewWindow) setupChromium() {
16991752
w.dropTarget = w32.NewDropTarget()
17001753
w.dropTarget.OnDrop = func(files []string, x int, y int) {
17011754
w.parent.emit(events.Windows.WindowDragDrop)
1702-
w.parent.InitiateFrontendDropProcessing(files, x, y)
1755+
fmt.Printf("[DragDropDebug] Windows DropTarget OnDrop: Raw screen coordinates: (%d, %d)\n", x, y)
1756+
1757+
// Convert screen coordinates to window-relative coordinates first
1758+
// Windows DropTarget gives us screen coordinates, but we need window-relative coordinates
1759+
windowRect := w32.GetWindowRect(w.hwnd)
1760+
windowRelativeX := x - int(windowRect.Left)
1761+
windowRelativeY := y - int(windowRect.Top)
1762+
1763+
fmt.Printf("[DragDropDebug] Windows DropTarget OnDrop: After screen-to-window conversion: (%d, %d)\n", windowRelativeX, windowRelativeY)
1764+
1765+
// Convert window-relative coordinates to webview-relative coordinates
1766+
webviewX, webviewY := w.convertWindowToWebviewCoordinates(windowRelativeX, windowRelativeY)
1767+
fmt.Printf("[DragDropDebug] Windows DropTarget OnDrop: Final webview coordinates: (%d, %d)\n", webviewX, webviewY)
1768+
w.parent.InitiateFrontendDropProcessing(files, webviewX, webviewY)
17031769
}
17041770
if opts.OnEnterEffect != 0 {
17051771
w.dropTarget.OnEnterEffect = convertEffect(opts.OnEnterEffect)
@@ -2026,7 +2092,15 @@ func (w *windowsWebviewWindow) processMessageWithAdditionalObjects(
20262092
}
20272093
}
20282094

2029-
w.parent.InitiateFrontendDropProcessing(filenames, x, y)
2095+
fmt.Printf("[DragDropDebug] processMessageWithAdditionalObjects: Raw WebView2 coordinates: (%d, %d)\n", x, y)
2096+
2097+
// Convert webview-relative coordinates to window-relative coordinates, then to webview-relative coordinates
2098+
// Note: The coordinates from WebView2 are already webview-relative, but let's log them for debugging
2099+
webviewX, webviewY := x, y
2100+
2101+
fmt.Printf("[DragDropDebug] processMessageWithAdditionalObjects: Using coordinates as-is (already webview-relative): (%d, %d)\n", webviewX, webviewY)
2102+
2103+
w.parent.InitiateFrontendDropProcessing(filenames, webviewX, webviewY)
20302104
return
20312105
}
20322106
}

0 commit comments

Comments
 (0)