mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-16 23:55:52 +01:00
* fix(v3): overhaul drag-and-drop for Linux reliability and simplify Windows This commit fixes drag-and-drop reliability on Linux and simplifies the Windows implementation. ## Linux - Rewrite GTK drag handlers to properly intercept external file drops - Fix HTML5 internal drag-and-drop being broken when file drop enabled - Add hover effects during file drag operations - Fix multiple app instances interfering with each other ## Windows - Remove native IDropTarget in favor of JavaScript approach (matches v2) - File drops now handled via chrome.webview.postMessageWithAdditionalObjects ## All Platforms - Rename EnableDragAndDrop to EnableFileDrop - Rename data-wails-drop-target to data-file-drop-target - Rename wails-drop-target-active to file-drop-target-active - Add comprehensive drag-and-drop documentation ## Breaking Changes - EnableDragAndDrop -> EnableFileDrop - data-wails-dropzone -> data-file-drop-target - wails-dropzone-hover -> file-drop-target-active - DropZoneDetails -> DropTargetDetails - Remove WindowDropZoneFilesDropped event (use WindowFilesDropped) * feat(macos): optimize drag event performance with debouncing and caching - Add 50ms debouncing to limit drag events to 20/sec (was 120/sec) - Implement window implementation caching to avoid repeated lookups - Maintain existing 5-pixel threshold for immediate response - Keep zero-allocation path with pre-allocated buffers - Rename linuxDragActive to nativeDragActive for clarity - Update IMPLEMENTATION.md with optimization details and Windows guidance Performance improvements: - 83% reduction in event frequency - ~6x reduction in CPU/memory usage during drag operations - Maintains smooth visual feedback with InvokeSync for timer callbacks * fix(windows): implement proper file drop support for Windows - Remove incorrect AllowExternalDrag(false) call that was blocking file drops - Fix message prefix from 'FilesDropped' to 'file:drop:' to match JS runtime - Fix coordinate parsing for 'file:drop:x:y' format (indices 2,3 not 1,2) - Add enableFileDrop flag injection to JS runtime during navigation - Update JS runtime to check enableFileDrop flag before processing drops - Always call preventDefault() to stop browser navigation on file drags - Show 'no drop' cursor when file drops are disabled - Update example to filter file drags from HTML drop zone handlers - Add documentation for combining file drop with HTML drag-and-drop * fix(v3): block file drops on Linux when EnableFileDrop is false - Add disableDND() to intercept and reject external file drags at GTK level - Show 'no drop' cursor when files are dragged over window - Allow internal HTML5 drag-and-drop to work normally - Initialize _wails.flags object in runtime core to prevent undefined errors - Inject enableFileDrop flag on Linux and macOS (matching Windows) - Fix bare _wails reference to use window._wails - Update docs with info about blocked drops and combining with HTML DnD * fix(darwin): add missing fmt import in webview_window_darwin.go * fix(macOS): implement hover effects for file drag-and-drop with optimizations - Added draggingUpdated: handler to track mouse movement during drag operations - Implemented macosOnDragEnter/Exit/Over export functions for real-time hover state - Fixed JS function call from '_wails.handlePlatformFileDrop' to correct 'wails.Window.HandlePlatformFileDrop' - Added EnableFileDrop flag checks to prevent hover effects when file drops are disabled - Renamed linuxDragActive to nativeDragActive for cross-platform consistency Performance optimizations: - Added 50ms debounce to reduce event frequency from ~120/sec to ~20/sec - Implemented 5-pixel movement threshold for immediate response - Added window caching with sync.Map to avoid repeated lookups - Zero-allocation JavaScript calls with pre-allocated 128-byte buffer - Reduced memory usage to ~18 bytes per event (6x reduction) Build improvements: - Updated runtime Taskfile to include documentation generation - Added docs:build task to runtime build process - Fixed build order: events → docs → runtime Documentation: - Added IMPLEMENTATION.md with optimization details - Included guidance for Windows implementation * chore(v3/examples): remove html-dnd-api example The drag-n-drop example now demonstrates both external file drops and internal HTML5 drag-and-drop, making this separate example redundant. * docs(v3): move drag-and-drop implementation details to runtime-internals - Add drag-and-drop section to contributing/runtime-internals.mdx - Remove IMPLEMENTATION.md from example (content now in proper docs) - Covers platform differences, debugging tips, and key files * fix(v3): remove html-dnd-api from example build list * fix(v3): remove duplicate json import in application_darwin.go * fix(v3): address CodeRabbit review feedback - Fix docs to use app.Window.NewWithOptions() instead of deprecated API - Add mutex protection to dragOverJSBuffer to prevent race conditions - Add mutex protection to dragThrottleState fields for thread safety * docs: add coderabbit pre-push requirement to AGENTS.md * fix(v3/test): use correct CSS class name file-drop-target-active * chore(v3/test): remove dnd-test directory This was a development test file that shouldn't be in the PR. The drag-n-drop example serves as the proper test case. * docs(v3): update Windows file drop comment to reflect implemented fix Remove stale TODO - enableFileDrop flag is now injected in navigationCompleted * refactor(v3): make handleDragAndDropMessage unexported Internal method only called by application event loop, not part of public API.
237 lines
7.7 KiB
Go
237 lines
7.7 KiB
Go
package main
|
|
|
|
import (
|
|
_ "embed"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"log"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"github.com/wailsapp/wails/v3/pkg/application"
|
|
)
|
|
|
|
//go:embed index.html
|
|
var indexHTML string
|
|
|
|
//go:embed wails-logo.png
|
|
var wailsLogo []byte
|
|
|
|
func main() {
|
|
app := application.New(application.Options{
|
|
Name: "Wails Liquid Glass Demo",
|
|
Description: "Demonstrates the native Liquid Glass effect on macOS",
|
|
})
|
|
|
|
// Check if running on macOS
|
|
if runtime.GOOS != "darwin" {
|
|
// Show dialog for non-macOS platforms
|
|
app.Dialog.Info().
|
|
SetTitle("macOS Only Demo").
|
|
SetMessage("The Liquid Glass effect is a macOS-specific feature that uses native NSGlassEffectView (macOS 15.0+) or NSVisualEffectView.\n\nThis demo is not available on " + runtime.GOOS + ".").
|
|
Show()
|
|
fmt.Println("The Liquid Glass effect is a macOS-specific feature. This demo is not available on", runtime.GOOS)
|
|
return
|
|
}
|
|
|
|
// Convert logo to base64 data URI
|
|
logoDataURI := "data:image/png;base64," + base64.StdEncoding.EncodeToString(wailsLogo)
|
|
|
|
// Create different HTML for each window
|
|
lightHTML := strings.Replace(indexHTML, "wails-logo.png", logoDataURI, 1)
|
|
lightHTML = strings.Replace(lightHTML, "LIQUID GLASS", "Light Style", 1)
|
|
|
|
darkHTML := strings.Replace(indexHTML, "wails-logo.png", logoDataURI, 1)
|
|
darkHTML = strings.Replace(darkHTML, "LIQUID GLASS", "Dark Style", 1)
|
|
|
|
vibrantHTML := strings.Replace(indexHTML, "wails-logo.png", logoDataURI, 1)
|
|
vibrantHTML = strings.Replace(vibrantHTML, "LIQUID GLASS", "Vibrant Style", 1)
|
|
|
|
tintedHTML := strings.Replace(indexHTML, "wails-logo.png", logoDataURI, 1)
|
|
tintedHTML = strings.Replace(tintedHTML, "LIQUID GLASS", "Blue Tint", 1)
|
|
|
|
sheetHTML := strings.Replace(indexHTML, "wails-logo.png", logoDataURI, 1)
|
|
sheetHTML = strings.Replace(sheetHTML, "LIQUID GLASS", "Sheet Material", 1)
|
|
|
|
hudHTML := strings.Replace(indexHTML, "wails-logo.png", logoDataURI, 1)
|
|
hudHTML = strings.Replace(hudHTML, "LIQUID GLASS", "HUD Window", 1)
|
|
|
|
contentHTML := strings.Replace(indexHTML, "wails-logo.png", logoDataURI, 1)
|
|
contentHTML = strings.Replace(contentHTML, "LIQUID GLASS", "Content Background", 1)
|
|
|
|
// Window 1: Light style with no tint
|
|
window1 := app.Window.NewWithOptions(application.WebviewWindowOptions{
|
|
Title: "Light Glass",
|
|
Width: 350,
|
|
Height: 280,
|
|
X: 100,
|
|
Y: 100,
|
|
Frameless: true,
|
|
EnableFileDrop: false,
|
|
HTML: lightHTML,
|
|
InitialPosition: application.WindowXY,
|
|
Mac: application.MacWindow{
|
|
Backdrop: application.MacBackdropLiquidGlass,
|
|
InvisibleTitleBarHeight: 500,
|
|
LiquidGlass: application.MacLiquidGlass{
|
|
Style: application.LiquidGlassStyleLight,
|
|
Material: application.NSVisualEffectMaterialAuto,
|
|
CornerRadius: 20.0,
|
|
TintColor: nil,
|
|
},
|
|
},
|
|
})
|
|
|
|
// Window 2: Dark style
|
|
window2 := app.Window.NewWithOptions(application.WebviewWindowOptions{
|
|
Title: "Dark Glass",
|
|
Width: 350,
|
|
Height: 280,
|
|
X: 500,
|
|
Y: 100,
|
|
Frameless: true,
|
|
EnableFileDrop: false,
|
|
HTML: darkHTML,
|
|
InitialPosition: application.WindowXY,
|
|
Mac: application.MacWindow{
|
|
Backdrop: application.MacBackdropLiquidGlass,
|
|
InvisibleTitleBarHeight: 500,
|
|
LiquidGlass: application.MacLiquidGlass{
|
|
Style: application.LiquidGlassStyleDark,
|
|
Material: application.NSVisualEffectMaterialAuto,
|
|
CornerRadius: 20.0,
|
|
TintColor: nil,
|
|
},
|
|
},
|
|
})
|
|
|
|
// Window 3: Vibrant style
|
|
window3 := app.Window.NewWithOptions(application.WebviewWindowOptions{
|
|
Title: "Vibrant Glass",
|
|
Width: 350,
|
|
Height: 280,
|
|
X: 900,
|
|
Y: 100,
|
|
Frameless: true,
|
|
EnableFileDrop: false,
|
|
HTML: vibrantHTML,
|
|
InitialPosition: application.WindowXY,
|
|
Mac: application.MacWindow{
|
|
Backdrop: application.MacBackdropLiquidGlass,
|
|
InvisibleTitleBarHeight: 500,
|
|
LiquidGlass: application.MacLiquidGlass{
|
|
Style: application.LiquidGlassStyleVibrant,
|
|
Material: application.NSVisualEffectMaterialAuto,
|
|
CornerRadius: 20.0,
|
|
TintColor: nil,
|
|
},
|
|
},
|
|
})
|
|
|
|
// Window 4: Blue tinted glass
|
|
window4 := app.Window.NewWithOptions(application.WebviewWindowOptions{
|
|
Title: "Tinted Glass",
|
|
Width: 350,
|
|
Height: 280,
|
|
X: 300,
|
|
Y: 420,
|
|
Frameless: true,
|
|
EnableFileDrop: false,
|
|
HTML: tintedHTML,
|
|
InitialPosition: application.WindowXY,
|
|
Mac: application.MacWindow{
|
|
Backdrop: application.MacBackdropLiquidGlass,
|
|
InvisibleTitleBarHeight: 500,
|
|
LiquidGlass: application.MacLiquidGlass{
|
|
Style: application.LiquidGlassStyleLight,
|
|
Material: application.NSVisualEffectMaterialAuto,
|
|
CornerRadius: 25.0, // Different corner radius
|
|
TintColor: &application.RGBA{Red: 0, Green: 100, Blue: 200, Alpha: 50}, // Blue tint
|
|
},
|
|
},
|
|
})
|
|
|
|
// Window 5: Using specific NSVisualEffectMaterial
|
|
window5 := app.Window.NewWithOptions(application.WebviewWindowOptions{
|
|
Title: "Sheet Material",
|
|
Width: 350,
|
|
Height: 280,
|
|
X: 700,
|
|
Y: 420,
|
|
Frameless: true,
|
|
EnableFileDrop: false,
|
|
HTML: sheetHTML,
|
|
InitialPosition: application.WindowXY,
|
|
Mac: application.MacWindow{
|
|
Backdrop: application.MacBackdropLiquidGlass,
|
|
InvisibleTitleBarHeight: 500,
|
|
LiquidGlass: application.MacLiquidGlass{
|
|
Style: application.LiquidGlassStyleAutomatic, // Automatic style
|
|
Material: application.NSVisualEffectMaterialSheet, // Specific material
|
|
CornerRadius: 15.0, // Different corner radius
|
|
TintColor: nil,
|
|
},
|
|
},
|
|
})
|
|
|
|
// Window 6: HUD Window Material (very light, translucent)
|
|
window6 := app.Window.NewWithOptions(application.WebviewWindowOptions{
|
|
Title: "HUD Window",
|
|
Width: 350,
|
|
Height: 280,
|
|
X: 100,
|
|
Y: 740,
|
|
Frameless: true,
|
|
EnableFileDrop: false,
|
|
HTML: hudHTML,
|
|
InitialPosition: application.WindowXY,
|
|
Mac: application.MacWindow{
|
|
Backdrop: application.MacBackdropLiquidGlass,
|
|
InvisibleTitleBarHeight: 500,
|
|
LiquidGlass: application.MacLiquidGlass{
|
|
Style: application.LiquidGlassStyleAutomatic,
|
|
Material: application.NSVisualEffectMaterialHUDWindow, // HUD Window material - very light
|
|
CornerRadius: 30.0, // Larger corner radius
|
|
TintColor: nil,
|
|
},
|
|
},
|
|
})
|
|
|
|
// Window 7: Content Background Material
|
|
window7 := app.Window.NewWithOptions(application.WebviewWindowOptions{
|
|
Title: "Content Background",
|
|
Width: 350,
|
|
Height: 280,
|
|
X: 500,
|
|
Y: 740,
|
|
Frameless: true,
|
|
EnableFileDrop: false,
|
|
HTML: contentHTML,
|
|
InitialPosition: application.WindowXY,
|
|
Mac: application.MacWindow{
|
|
Backdrop: application.MacBackdropLiquidGlass,
|
|
InvisibleTitleBarHeight: 500,
|
|
LiquidGlass: application.MacLiquidGlass{
|
|
Style: application.LiquidGlassStyleAutomatic,
|
|
Material: application.NSVisualEffectMaterialContentBackground, // Content background
|
|
CornerRadius: 10.0, // Smaller corner radius
|
|
TintColor: &application.RGBA{Red: 0, Green: 200, Blue: 100, Alpha: 30}, // Warm tint
|
|
},
|
|
},
|
|
})
|
|
|
|
// Show all windows
|
|
window1.Show()
|
|
window2.Show()
|
|
window3.Show()
|
|
window4.Show()
|
|
window5.Show()
|
|
window6.Show()
|
|
window7.Show()
|
|
|
|
// Run the application
|
|
err := app.Run()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|