* fix(macOS): run getCurrentWindowID on main thread and add nil checks
AppKit must be used on the main thread. getCurrentWindowID could be called from arbitrary Go goroutines, so dispatch to the main queue when not already on the main thread. Also guard NSApp, window, and delegate with nil checks and fall back to mainWindow when keyWindow is nil to avoid wrong or missing window ID.
* Update UNRELEASED_CHANGELOG.md
* Update UNRELEASED_CHANGELOG.md
* Update UNRELEASED_CHANGELOG.md
* fix: consistent indentation and changelog formatting
- Convert spaces to tabs in getCurrentWindowID() for codebase consistency
- Move changelog entry below the <!-- Bug fixes --> comment
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* [v3]docs: Corrected Listening to Events In Javascript
After using the wails3 an dfollowing docs, I found Events being mostly correct except this, hope it helps others who use the docs.
Signed-off-by: Abdelhadi Seddar <91424903+AbdelhadiSeddar@users.noreply.github.com>
* [v3] docs: Replaced all Instances of `Event`
Commit according to CodeRabbit's Input
Signed-off-by: Abdelhadi Seddar <91424903+AbdelhadiSeddar@users.noreply.github.com>
* [v3]docs Fixed inconsistencies in last docs commit
According to CodeRabbit's Review
Signed-off-by: Abdelhadi Seddar <91424903+AbdelhadiSeddar@users.noreply.github.com>
* [v3] docs: use `const` for variables in event listener examples.
Signed-off-by: Abdelhadi Seddar <91424903+AbdelhadiSeddar@users.noreply.github.com>
---------
Signed-off-by: Abdelhadi Seddar <91424903+AbdelhadiSeddar@users.noreply.github.com>
Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
* feat(v3): add file-input example for issue #4862
Minimal example demonstrating HTML file input functionality:
- Single file selection
- Multiple file selection
- Files or directories (webkitdirectory)
- Accept filter (note: not enforced by macOS)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor(example): use JS runtime dialog API instead of Go backend
Update file-input example to use wails.Dialogs.OpenFile() from the
JS runtime instead of a custom Go FileService backend. This demonstrates
the recommended approach for dialog functionality.
Fixes#4862
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor(example): use generated bindings for dialog API
Update file-input example to use proper generated bindings instead
of inline JS runtime calls. The example now demonstrates:
- HTML file input elements (single, multiple, webkitdirectory)
- Wails Dialog API via generated FileService bindings
Fixes#4862
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: add changelog entry for macOS file input fix
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* fix(runtime): use internal path for HandlePlatformFileDrop
The Go backend was calling window.wails.Window.HandlePlatformFileDrop()
for native file drops on macOS/Linux. This only worked with the bundled
runtime which sets window.wails = Runtime.
When using the @wailsio/runtime npm module, window.wails is an empty
object because the npm module only exports via ES modules and registers
the handler at window._wails.handlePlatformFileDrop.
Changed the Go code to call the internal path that both runtime
distributions set up: window._wails.handlePlatformFileDrop()
Also added a test case that uses the npm module to verify the fix.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: add changelog entry for npm runtime DND fix
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* chore: add built frontend dist for dnd-npm-runtime test
Required for go:embed to work in CI.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: update README to reflect pre-built frontend
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Add test case for aliases of imported types
* Replace `typeutil.Map` with object-keyed map in `addTypeImpl` method
* Replace `typeutil.Map` with object-keyed map in `needsCreateImpl` method
* Update UNRELEASED_CHANGELOG.md
* Update binding generator test data
---------
Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
Add WKUIDelegate protocol support to handle runOpenPanelWithParameters
delegate method, which is required for <input type="file"> elements to
work in WKWebView on macOS. This was a regression from V2 which had
this implementation.
Changes:
- Add WKUIDelegate to WebviewWindowDelegate protocol list
- Set UIDelegate on WKWebView during window creation
- Implement runOpenPanelWithParameters to show NSOpenPanel for file selection
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(v3/linux): fix OpenFileDialog crash from GTK thread violation
The runChooserDialog function had a race condition that caused GTK
assertion failures and crashes on Linux:
1. InvokeAsync scheduled gtk_dialog_run on the GTK thread
2. After dialog closed, a goroutine was spawned OFF the GTK thread
3. gtk_widget_destroy was called immediately (before goroutine ran)
4. Goroutine tried to call gtk_file_chooser_get_filenames on destroyed widget
Fix:
- Extract filenames on GTK thread BEFORE destroying widget
- Call gtk_widget_destroy on GTK thread AFTER extraction
- Goroutine only handles sending Go strings (no GTK calls)
Fixes#3683
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: add changelog entry for OpenFileDialog crash fix
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: properly free all filenames to prevent memory leak
When more than 1024 files are selected, the previous code leaked memory
because g_slist_free() only frees list nodes, not the data pointers.
Now we iterate through ALL entries, freeing each filename string.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor: remove arbitrary 1024 file selection limit
GTK's gtk_file_chooser_get_filenames() has no documented maximum.
The limit was arbitrary and unnecessary.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: add comment about no file selection limit
Consistent with Windows/macOS behavior.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: ddmoney420 <ddmoney420@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
* fix(v3): add nil check to Focus() to prevent SIGSEGV after Hide
The Focus() method was missing a nil/destroyed check on w.impl,
causing a SIGSEGV when Focus() is called on a window that has been
hidden and potentially destroyed (e.g., when clicking the dock icon
after hiding the window on macOS).
This aligns Focus() with Show() and Hide() which already have proper
guards against nil/destroyed window implementations.
Fixes#4890
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: add changelog entry for Focus() nil check fix
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: ddmoney420 <ddmoney420@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
* fix(v3/windows): Move browser flags to application-level options (#4559)
WebView2 shares a single browser environment per user data path, so
browser flags (EnabledFeatures, DisabledFeatures, AdditionalBrowserArgs)
must be set at application level, not per-window.
Changes:
- Add EnabledFeatures, DisabledFeatures, AdditionalBrowserArgs to
application.Options.Windows
- Mark per-window equivalents in WindowsWindow as deprecated
- Update webview_window_windows.go to read from app-level options
This fixes the crash when opening a second window with different
browser flags.
Fixes#4559
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: address PR review comments
- Remove incorrectly added WebviewGpuPolicy field from WindowsOptions
(it's a Linux-specific option that already exists in LinuxWindow)
- Clarify changelog: AdditionalLaunchArgs was renamed to AdditionalBrowserArgs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor!: remove per-window browser flags (breaking change)
BREAKING CHANGE: Remove EnabledFeatures, DisabledFeatures, and
AdditionalLaunchArgs from per-window WindowsWindow options.
Use application-level options instead:
- Options.Windows.EnabledFeatures
- Options.Windows.DisabledFeatures
- Options.Windows.AdditionalBrowserArgs
These flags apply globally to the shared WebView2 environment,
so per-window configuration was never actually supported.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: add documentation for application-level browser flags
- Document EnabledFeatures, DisabledFeatures, AdditionalBrowserArgs
- Add examples showing how to configure WebView2 browser flags
- Explain that these flags apply globally to all windows
- Update application API reference with platform-specific options
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* chore: simplify browser flags documentation
Remove unnecessary warnings and overly prescriptive comments.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: clarify that AdditionalBrowserArgs requires -- prefix
Chromium command-line switches require the -- prefix.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Accept obscure update to package-lock.json
* Make global state local in Collector.IsVoidAlias predicate
* Add protection against potential nil dereference
* Update test data
* Fix typo in doc comment
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* Update UNRELEASED_CHANGELOG.md
---------
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* fix(v3): guard dispatchWailsEvent against race condition on reload
When the page is reloaded, the WindowLoadFinished event can fire before
the JavaScript runtime has mounted dispatchWailsEvent on window._wails.
This causes a TypeError: window._wails.dispatchWailsEvent is not a function.
This fix adds a guard to check if window._wails and dispatchWailsEvent
exist before attempting to call the function. If the runtime isn't ready,
the event is silently skipped (which is correct since there's no handler).
Fixes#4872
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: Add changelog entry for #4872
---------
Co-authored-by: ddmoney420 <ddmoney420@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
* feat(v3): Add UseApplicationMenu option for cross-platform menu support
Add `UseApplicationMenu` option to `WebviewWindowOptions` that allows
windows on Windows and Linux to inherit the application menu set via
`app.Menu.Set()`.
This provides a simpler cross-platform approach:
- On macOS: No effect (app menu is always global)
- On Windows/Linux: Window displays the application menu
Benefits:
- Eliminates need for platform-specific menu code
- Per-window opt-in maintains backwards compatibility
- Explicit window menus still take priority
Updated:
- webview_window_options.go: Added UseApplicationMenu bool field
- webview_window_windows.go: Check UseApplicationMenu when no window menu set
- webview_window_linux.go: Check UseApplicationMenu when no window menu set
- examples/dialogs: Use UseApplicationMenu instead of conditional SetMenu
- examples/menu: Use UseApplicationMenu instead of explicit SetMenu
- docs: Updated menu and window options documentation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: Remove incorrect 'Menu Options' section header
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* fix: make menus to be displayed on Windows OS in `v3\examples\dialogs`
* refactor: use cross-platform user home dir in `v3/examples/dialogs/main.go`
* fix: handle os.UserHomeDir() error with fallback to os.TempDir()
* fix: use = instead of := for err (already declared)
---------
Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
Change nil checks to length checks before accessing Icon[0] to prevent
panic when Icon is an empty slice rather than nil.
Fixes#3631
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(v3): add nil check to Focus() to prevent SIGSEGV after Hide
The Focus() method was missing a nil/destroyed check on w.impl,
causing a SIGSEGV when Focus() is called on a window that has been
hidden and potentially destroyed (e.g., when clicking the dock icon
after hiding the window on macOS).
This aligns Focus() with Show() and Hide() which already have proper
guards against nil/destroyed window implementations.
Fixes#4890
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(v3/linux): use g_bytes_new instead of g_bytes_new_static for Go slices
g_bytes_new_static expects truly static data that is never freed or
moved, but Go's garbage collector can move or free slice memory at any
time. This causes SIGSEGV crashes in the GTK event loop when the GC
runs and frees memory that GTK still references.
The fix replaces g_bytes_new_static with g_bytes_new, which copies the
data to C-owned memory that is safe from Go's GC.
Also fixes memory leak in setIcon() by adding proper g_bytes_unref and
g_object_unref calls for the GBytes and stream objects.
Changes:
- linux_cgo.go: Replace g_bytes_new_static with g_bytes_new (4 places)
- linux_cgo.go: Add cleanup in setIcon() for gbytes and stream
- linux_purego.go: Add gBytesNew binding and use it instead of static
Fixes#4864
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(linux): add empty slice guards to prevent panic
Adds guards to check for empty slices before taking &slice[0] which
would panic on empty input. Affects setIcon(), menuItemAddProperties(),
menuItemSetBitmap(), and runQuestionDialog() in both CGO and purego.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: ddmoney420 <ddmoney420@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
Adds guards to check for empty slices before taking &slice[0] which would
panic. Affects setIcon(), menuItemAddProperties(), menuItemSetBitmap(),
and runQuestionDialog() in both CGO and purego implementations.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use ubuntu-24.04-arm runner for linux/arm64 cross-compile tests
instead of QEMU emulation. This should reduce build time from ~20min
to ~3min.
- Remove QEMU and Buildx setup (not needed with native runner)
- Remove --platform flag from Docker commands
- Each matrix entry now specifies its runner
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat(icons): implement Mac asset (.car) generation with actool
- Check actool version >= 26 requirement
- Generate asset.car from Icon Composer input
- Validate compilation output and cleanup temp files
* Wails Icon as Icon Composer file
* a generated assets.car from the wails icon
* handle absolute paths correctly in actool command
- Check if paths are absolute before prepending "./"
- Use filepath.Join for temp.plist path construction
* add test for Assets.car generation
* Skipping Asset.car generation and test on non mac-systems
* add CFBundleIconName generation to plist, if Assets.car exists
* also create .icns from .icon-File and use always absolut path
Use absolut path, because otherwise we got strange behavior from actool.
* update to use appicon as CFBundleIconName and optionally use the name from config
* update the Taskfiles
* remove log prints
* the awesome new LiquidGlass icon files
* update doc
* Update UNRELEASED_CHANGELOG.md
* Update UNRELEASED_CHANGELOG.md
* fix security bug
* Skip icon generation test with actool on CI
* fix error from coderabbitai
* solved the coderabbitai nitpicks
* fix coderabbitai findings
* Update changelog
---------
Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
For Linux ARM64 builds on x86_64 hosts, use Docker's QEMU emulation
instead of trying to cross-compile with Zig or install multi-arch packages.
Changes:
- Workflow: Set up QEMU and Docker Buildx for Linux cross-arch builds
- Workflow: Build Docker image with --platform for target architecture
- Dockerfile: Simplify to use native GCC (QEMU handles arch translation)
- Taskfile: Add --platform flag to docker run for Linux builds
This approach is slower but reliable and doesn't require complex
cross-compilation toolchain setup.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Instead of trying to use Zig for Linux cross-compilation (which has
glibc header compatibility issues), install the proper aarch64-linux-gnu
cross-compilation toolchain and ARM64 GTK/WebKit libraries.
Changes:
- Enable multi-arch and install gcc-aarch64-linux-gnu toolchain
- Install ARM64 versions of libgtk-3-dev and libwebkit2gtk-4.1-dev
- Set PKG_CONFIG_PATH for ARM64 libraries when cross-compiling
- Use aarch64-linux-gnu-gcc as the cross-compiler
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add Zig CC wrappers for Linux ARM64 and AMD64 targets. The build script
now detects if host architecture matches target architecture:
- If match: use native GCC (faster, better optimization)
- If different: use Zig for cross-compilation
This allows building Linux ARM64 binaries from an x86_64 Docker host
without requiring multi-arch images or QEMU emulation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The wails-cross image is an x86_64 image that uses Zig for cross-compilation.
It doesn't need to run ON the target platform - it cross-compiles TO it.
Remove the --platform flag that was causing Docker to try pulling a
non-existent arm64 version of the image.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When building Linux binaries with a different target architecture than
the host (e.g., arm64 on x86_64), use Docker-based cross-compilation
instead of native build. The native GCC cannot compile ARM64 assembly
on an x86_64 host.
Adds a third condition to the build task selection: target architecture
must match host architecture to use native build.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Docker mounts v3 at the same absolute path, so change the replace
directive to use the absolute workspace path instead of removing it.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The project created by wails3 init has a replace directive pointing
to the local v3 source. This doesn't work inside Docker containers.
Remove it before running the cross-compile tasks.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- common:setup:docker instead of setup:docker
- darwin:build, linux:build, windows:build instead of build:darwin, etc.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The wails3 CLI requires webkit2gtk, gtk, and other Linux libraries
to compile due to CGO dependencies.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Instead of building Docker images from scratch, the workflow now:
- Installs wails3 CLI
- Creates a test project with wails3 init
- Runs setup:docker to build the cross-compile image
- Uses task build:<platform> for cross-compilation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Dockerfiles use heredoc syntax which requires BuildKit's
dockerfile:1 syntax directive to parse correctly.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds registry-based cache alongside GHA cache to improve build times
when GHA cache is evicted (7-day retention limit).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Always use linux:build:docker for Linux targets to properly test
the Docker image for both amd64 and arm64 architectures.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Intel Macs are EOL (last released 2020, support ending ~2027).
Focus testing on darwin/arm64 which is the current/future platform.
The Dockerfile still supports amd64 if needed.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The task uses --platform flag which requires the matching architecture
variant. Pull arm64 variant explicitly for Linux arm64 test.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The linux:build task chooses native build when gcc is available,
but native x86_64 gcc can't cross-compile to arm64 (assembly errors).
Explicitly call linux:build:docker for Linux arm64 target.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The wails3 task system expects a locally tagged 'wails-cross' image.
Pull from ghcr.io and tag it appropriately before running tasks.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
wails3 init already adds a replace directive with relative path.
Use sed to update it to absolute path instead of adding a duplicate.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use `wails3 task {os}:build` instead of manual Docker commands
- Test actual cross-compilation only (skip host-to-host):
- darwin/arm64 from Linux/amd64
- windows/arm64 from Linux/amd64
- linux/arm64 from Linux/amd64
- Let task system handle frontend build, bindings, etc.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The frontend build requires Go bindings to be generated first.
Run `wails3 generate bindings` on the host before building frontend.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use 3 parallel jobs (darwin, linux, windows) instead of 6
- Each job builds both amd64 and arm64 architectures
- Use real wails3 projects via `wails3 init` instead of fake test programs
- Remove pointless non-CGO tests
- Keep library dependency verification for Linux binaries
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>