feat(linux): flip GTK4 + WebKitGTK 6.0 to the default build (#5459)#5463
Conversation
For v3.0.0 GA, GTK4 + WebKitGTK 6.0 becomes the default Linux build stack.
GTK3 + WebKit2GTK 4.1 becomes a legacy opt-in via `-tags gtk3` for one v3
cycle and is scheduled for removal in v3.1.
Build-tag and file renames:
- Files previously named `*_linux_gtk4.go` (and .c/.h siblings) become the
bare `*_linux.go` default with constraint `linux && cgo && !gtk3 && ...`
- Files previously named `*_linux.go` become `*_linux_gtk3.go` with
constraint `linux && cgo && gtk3 && ...`
- `webkit6.go` -> `webkit_linux.go`; `webkit2.go` -> `webkit_linux_gtk3.go`
- The `gtk4` build tag is retired in favor of `gtk3` as the toggle
- `linux_cgo.c` / `.h` cgo build directives and `#include` / header guards
updated to match the new filename
- `gtk4-benchmark` directory kept by request (dev tool, both stacks tested
side-by-side); only constraint logic flipped
Doctor:
- Legacy `internal/doctor/packagemanager/*.go` (7 files): inverted
required/optional polarity. `gtk4` / `webkitgtk-6.0` are now required,
`gtk3 (legacy)` / `webkit2gtk (legacy)` are optional.
- `pkg/doctor-ng/packagemanager/*.go` already had the correct polarity.
CI workflows (`.github/workflows/`):
- Both `libgtk-4-dev`/`libwebkitgtk-6.0-dev` and the GTK3 dev packages are
installed in build-and-test-v3 / cross-compile-test-v3 / build-cross-image
so both stacks stay tested.
- Step labels renamed: "GTK4 default" / "GTK3 legacy".
- `BUILD_TAGS=gtk4` -> `BUILD_TAGS=gtk3`; `-tags gtk4` -> `-tags gtk3`.
- Library-presence test in build-cross-image checks `libwebkitgtk-6.0.so`
and `libgtk-4.so` first.
- TestService skip moved: previously skipped under `-tags gtk4` due to
display issues in CI. Since GTK4 is now the default, the skip moves to
the default-test step. The legacy `-tags gtk3` step now runs all tests.
Taskfile:
- `v3/Taskfile.yaml`: `test:example:linux:gtk4` -> `test:example:linux:gtk3`,
`sanity:gtk4` -> `sanity:gtk3`, BUILD_TAGS comments and example hints
flipped.
- Per-app `internal/commands/build_assets/linux/Taskfile.yml` user template
unchanged - already passes `EXTRA_TAGS` generically.
Templates and example fixtures:
- `internal/commands/updatable_build_assets/linux/nfpm/nfpm.yaml.tmpl`:
default runtime deps -> `libgtk-4-1` / `libwebkitgtk-6.0-4`; RPM and Arch
overrides updated; legacy deps shown as a commented-out block for users
who build with `-tags gtk3`.
- All 7 example `nfpm.yaml` files under `v3/examples/*/build/linux/nfpm/`
bumped to match.
- `tests/gtk4-benchmark/README.md` build instructions flipped.
Docs (English canonical; `ja/` `ru/` `zh-cn/` `pt/` `zh-tw/` `de/` `ko/`
`fr/` will sync via Crowdin):
- `docs/.../guides/build/linux.mdx`: `## GTK4 Support (Experimental)` ->
`## Legacy GTK3 Support`. Package lists, build instructions, and the
caution callout rewritten for the new defaults.
- `docs/.../guides/build/building.mdx`, `docs/.../guides/cli.mdx`:
build-tag examples flipped to `-tags gtk3`.
- `docs/.../getting-started/installation.mdx`: GTK4 packages in the Linux
paragraph.
- `docs/.../quick-start/installation.mdx`: all four distro install snippets
bumped to GTK4 packages; legacy GTK3 callout retained.
- `docs/.../reference/dialogs.mdx`: `#### Linux GTK4 Limitations` ->
`#### Linux Dialog Behavior`. Table reframed for the new defaults.
- `docs/.../reference/window.mdx`: `MenuStyle` availability note clarified
(default GTK4 vs `-tags gtk3` legacy).
- `docs/.../contributing/{getting-started,setup}.mdx`: contributor Linux
setup updated to GTK4-default with a legacy-path note.
`AGENTS.md` and `IMPLEMENTATION.md`:
- `IMPLEMENTATION.md` gets Decision 1.1 (2026-05-16) recording the flip
rationale; Decision 1 (the original "GTK3 default + GTK4 experimental"
decision) is preserved and marked SUPERSEDED.
- `AGENTS.md` policy section updated to reflect the new defaults.
User-facing behavior changes:
- The "GTK4 + WebKitGTK 6.0 support is EXPERIMENTAL" stdout banner
printed at app startup is removed - GTK4 is no longer experimental.
- `icon lookup not implemented for GTK4` error message reworded to point
users at `-tags gtk3` as the workaround.
Cleanup:
- Removed `v3/test/manual/dialog/bin/file-*-gtk4*` and `message-*-gtk4*`
test binaries (committed during the original #4958 GTK4 dev work).
Verification:
- `go vet ./...` clean on darwin against this change (pre-existing
JSON-tag / MarshalJSON issues in `internal/generator/testcases` are
unrelated).
- Linux cgo build verification cannot be done from macOS; requires
`lin-node1` or equivalent before merge.
Refs #5459. Implements the default flip planned for v3.0.0-beta.1.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThis PR flips the Linux default to GTK4 + WebKitGTK 6.0 (no build tag) and makes GTK3 + WebKit2GTK 4.1 a legacy opt-in via ChangesGTK4 + WebKitGTK 6.0 Default Flip
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Possibly related PRs
Suggested labels
Suggested reviewers
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Pull request overview
This PR flips Wails v3’s default Linux GUI stack from GTK3 + WebKit2GTK 4.1 to GTK4 + WebKitGTK 6.0, making GTK3 a legacy opt-in via -tags gtk3 (scheduled for removal in v3.1). It updates build constraints/filenames accordingly and propagates the new default through CI, tooling (doctor/taskfile), packaging templates, and documentation.
Changes:
- Invert Linux build constraints so GTK4/WebKitGTK 6.0 is the default and GTK3/WebKit2GTK 4.1 is selected via
-tags gtk3. - Rename/split Linux implementation files (Go + cgo) to align with the new default/legacy stack.
- Update CI workflows, Taskfile targets, nfpm templates/examples, doctor package requirements, and docs to reflect the new default.
Reviewed changes
Copilot reviewed 59 out of 77 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| v3/tests/gtk4-benchmark/version_gtk4.go | Default benchmark build tag switched to !gtk3. |
| v3/tests/gtk4-benchmark/version_gtk3.go | Legacy benchmark build tag switched to gtk3. |
| v3/tests/gtk4-benchmark/README.md | Benchmark build instructions updated for GTK4 default / GTK3 legacy. |
| v3/Taskfile.yaml | Task hints/targets updated to reflect GTK4 default and gtk3 opt-in. |
| v3/pkg/application/menuitem_linux.go | GTK4-default Linux menu item implementation moved to default filename/tag. |
| v3/pkg/application/menuitem_linux_gtk3.go | GTK3 legacy Linux menu item implementation moved under gtk3 tag. |
| v3/pkg/application/menu_linux.go | GTK4-default Linux menu implementation moved to default filename/tag. |
| v3/pkg/application/menu_linux_gtk4.go | Removed (GTK4 code moved to default file). |
| v3/pkg/application/menu_linux_gtk3.go | Added as GTK3 legacy menu implementation (gtk3 tag). |
| v3/pkg/application/linux_cgo.h | Header renamed/guard updated; build tag flipped to !gtk3. |
| v3/pkg/application/linux_cgo.c | cgo C file renamed/include updated; build tag flipped to !gtk3. |
| v3/pkg/application/linux_cgo_gtk4.go | Removed (GTK4 cgo moved to default file). |
| v3/pkg/application/gtkdispatch_linux.go | GTK4-default dispatch implementation moved to default file/tag. |
| v3/pkg/application/gtkdispatch_linux_gtk4.go | Removed (functionality moved to default file). |
| v3/pkg/application/gtkdispatch_linux_gtk3.go | Added as GTK3 legacy dispatch implementation (gtk3 tag). |
| v3/pkg/application/application_linux.go | GTK4-default Linux app implementation moved to default file/tag; logging/env updated. |
| v3/pkg/application/application_linux_gtk4.go | Removed (GTK4 app code moved to default file). |
| v3/pkg/application/application_linux_gtk3.go | Added as GTK3 legacy app implementation (gtk3 tag). |
| v3/internal/operatingsystem/webkit_linux.go | Default pkg-config/include flipped to gtk4 + webkitgtk-6.0. |
| v3/internal/operatingsystem/webkit_linux_gtk3.go | Legacy pkg-config/include flipped to gtk+-3.0 + webkit2gtk-4.1. |
| v3/internal/doctor/packagemanager/apt.go | Doctor package requirements inverted (gtk4 required; gtk3 optional legacy). |
| v3/internal/doctor/packagemanager/dnf.go | Doctor package requirements inverted (gtk4 required; gtk3 optional legacy). |
| v3/internal/doctor/packagemanager/emerge.go | Doctor package requirements inverted (gtk4 required; gtk3 optional legacy). |
| v3/internal/doctor/packagemanager/eopkg.go | Doctor package requirements inverted (gtk4 required; gtk3 optional legacy). |
| v3/internal/doctor/packagemanager/nixpkgs.go | Doctor package requirements inverted (gtk4 required; gtk3 optional legacy). |
| v3/internal/doctor/packagemanager/pacman.go | Doctor package requirements inverted (gtk4 required; gtk3 optional legacy). |
| v3/internal/doctor/packagemanager/zypper.go | Doctor package requirements inverted (gtk4 required; gtk3 optional legacy). |
| v3/internal/commands/updatable_build_assets/linux/nfpm/nfpm.yaml.tmpl | Default runtime deps updated to GTK4/WebKitGTK 6.0; legacy deps documented. |
| v3/internal/capabilities/capabilities_linux.go | Default Linux capabilities updated to GTK4/WebKitGTK 6.0. |
| v3/internal/capabilities/capabilities_linux_gtk3.go | Legacy Linux capabilities updated to GTK3/WebKit2GTK 4.1. |
| v3/internal/assetserver/webview/webkit_linux.go | Default build tag flipped to !gtk3. |
| v3/internal/assetserver/webview/webkit_linux_gtk3.go | Legacy build tag flipped to gtk3. |
| v3/internal/assetserver/webview/responsewriter_linux.go | Default pkg-config/includes flipped to gtk4 + webkitgtk-6.0. |
| v3/internal/assetserver/webview/responsewriter_linux_gtk3.go | Legacy pkg-config/includes flipped to gtk+-3.0 + webkit2gtk-4.1. |
| v3/internal/assetserver/webview/request_linux.go | Default pkg-config/includes flipped to gtk4 + webkitgtk-6.0. |
| v3/internal/assetserver/webview/request_linux_gtk3.go | Legacy pkg-config/includes flipped to gtk+-3.0 + webkit2gtk-4.1. |
| v3/examples/webview-api-check/README.md | Example build docs updated for GTK4 default / GTK3 legacy. |
| v3/examples/notifications/build/linux/nfpm/nfpm.yaml | Example packaging deps updated to GTK4/WebKitGTK 6.0. |
| v3/examples/ios/build/linux/nfpm/nfpm.yaml | Example packaging deps updated to GTK4/WebKitGTK 6.0. |
| v3/examples/dock/build/linux/nfpm/nfpm.yaml | Example packaging deps updated to GTK4/WebKitGTK 6.0. |
| v3/examples/custom-protocol-example/build/linux/nfpm/nfpm.yaml | Example packaging deps updated to GTK4/WebKitGTK 6.0. |
| v3/examples/badge/build/linux/nfpm/nfpm.yaml | Example packaging deps updated to GTK4/WebKitGTK 6.0. |
| v3/examples/badge-custom/build/linux/nfpm/nfpm.yaml | Example packaging deps updated to GTK4/WebKitGTK 6.0. |
| v3/examples/android/build/linux/nfpm/nfpm.yaml | Example packaging deps updated to GTK4/WebKitGTK 6.0. |
| IMPLEMENTATION.md | Records Decision 1.1: GTK4 default / GTK3 legacy opt-in; marks Decision 1 as superseded. |
| docs/src/content/docs/reference/window.mdx | Updates wording for MenuStyle availability under new defaults. |
| docs/src/content/docs/reference/dialogs.mdx | Updates section/anchor to reflect GTK4 default dialog behavior + legacy notes. |
| docs/src/content/docs/quick-start/installation.mdx | Updates Linux dependency guidance for GTK4 default and -tags gtk3 legacy. |
| docs/src/content/docs/guides/cli.mdx | Updates CLI examples from -tags gtk4 to -tags gtk3. |
| docs/src/content/docs/guides/build/linux.mdx | Reframes Linux guide around GTK4 default and legacy GTK3 opt-in. |
| docs/src/content/docs/guides/build/building.mdx | Updates build-tag examples and links to legacy GTK3 section. |
| docs/src/content/docs/getting-started/installation.mdx | Updates Linux dependencies text for GTK4 default and legacy option. |
| docs/src/content/docs/contributing/setup.mdx | Updates contributor Linux dependency setup for both stacks. |
| docs/src/content/docs/contributing/getting-started.mdx | Updates contributor prerequisites for GTK4 default + legacy GTK3. |
| AGENTS.md | Updates repo policy to reflect GTK4 default and legacy GTK3 tracking expectations. |
| .github/workflows/cross-compile-test-v3.yml | Installs both GTK4/GTK3 stacks for cross-compile validation. |
| .github/workflows/build-cross-image.yml | Installs both stacks; updates shared-lib presence checks for GTK4/WebKitGTK 6.0. |
| .github/workflows/build-and-test-v3.yml | Renames steps and flips build tags for CI coverage of default/legacy stacks. |
Comments suppressed due to low confidence (2)
.github/workflows/build-and-test-v3.yml:122
- The step labels and the installed packages are inverted: the “GTK4 default” step installs GTK3/WebKit2GTK dev packages, and the “GTK3 legacy” step installs GTK4/WebKitGTK 6.0 dev packages. With GTK4 now default, this will break Linux builds/tests. Swap the package lists (and keep any extra runtime deps like xvfb/portal helpers on the correct step).
- name: Install linux dependencies (GTK4 default)
uses: awalsh128/cache-apt-pkgs-action@latest
if: matrix.os == 'ubuntu-latest'
with:
packages: libgtk-3-dev libwebkit2gtk-4.1-dev libwayland-dev build-essential pkg-config xvfb x11-xserver-utils at-spi2-core xdg-desktop-portal-gtk
version: 1.0
- name: Install linux dependencies (GTK3 legacy)
uses: awalsh128/cache-apt-pkgs-action@latest
if: matrix.os == 'ubuntu-latest'
with:
packages: libgtk-4-dev libwebkitgtk-6.0-dev
version: 1.0
.github/workflows/build-and-test-v3.yml:239
- Same inversion as above in the templates job: the “GTK4 default” install step still installs GTK3/WebKit2GTK dev packages, while the “GTK3 legacy” step installs GTK4/WebKitGTK 6.0 dev packages. Swap these lists so the default build has the correct headers/libs available.
- name: Install linux dependencies (GTK4 default)
uses: awalsh128/cache-apt-pkgs-action@latest
if: matrix.os == 'ubuntu-latest'
with:
packages: libgtk-3-dev libwebkit2gtk-4.1-dev libwayland-dev build-essential pkg-config
version: 1.0
- name: Install linux dependencies (GTK3 legacy)
uses: awalsh128/cache-apt-pkgs-action@latest
if: matrix.os == 'ubuntu-latest'
with:
packages: libgtk-4-dev libwebkitgtk-6.0-dev
version: 1.0
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| impl := menu.impl.(*linuxMenu) | ||
| if impl.processed { | ||
| // Menu already processed, skip re-processing to avoid duplicates | ||
| return | ||
| } | ||
| impl.processed = true |
There was a problem hiding this comment.
Confirmed real, but pre-existing — this code was inherited verbatim from the original menu_linux_gtk4.go (added by #4958) which I renamed in-place. The bug is in the GTK4 implementation, not introduced by the default-flip. git blame on master against menu_linux_gtk4.go line 24 (the equivalent line before this PR) confirms the processed guard predates this change.
This PR is mechanical-flip-only scope. I don't want to bundle behavior fixes into the build-tag rename — too easy to mask one in the diff noise of the other. Filing as a follow-up issue against the menu implementation; will reference back here for context.
For reviewers: menu_linux_gtk3.go (the legacy file) has the exact same logic, so the bug affects both stacks identically.
- Add `!server` to the default GTK4 build constraint on the 4 .go files
that lost it during the gtk4 -> default rename, plus the .c/.h cgo
siblings for symmetry: application_linux.go, linux_cgo.{go,c,h},
menu_linux.go, menuitem_linux.go. Before this fix, building a server
app (-tags server) on Linux with cgo would still try to compile the
GTK4/WebKitGTK 6.0 implementation, causing duplicate symbols and
unnecessary cgo dependencies. Now symmetric with the *_gtk3.go files.
- Fix inverted package lists in .github/workflows/build-and-test-v3.yml.
The "Install linux dependencies (GTK4 default)" step was still
installing the GTK3 dev packages; the "(GTK3 legacy)" step had the
GTK4 packages. Labels matched the post-flip world but contents
didn't. Swap them so each step actually installs what its label
says. Both steps still run on every ubuntu-latest job (cache-apt-pkgs
is idempotent), so both stacks are present regardless of which build
is exercised next.
Verified on Ubuntu 26.04 lin-node1: `go build ./...` (default GTK4),
`go build -tags gtk3 ./...` (legacy), and `go build -tags server ./...`
all exit 0.
Refs #5459, PR #5463.
|
Pushed de9b677 addressing the review feedback. Summary per comment:
Re-verification on lin-node1 (Ubuntu 26.04, both stacks installed)
The |
There was a problem hiding this comment.
Actionable comments posted: 14
🧹 Nitpick comments (1)
v3/pkg/application/application_linux.go (1)
308-324: 💤 Low valueUnnecessary blank identifier assignments.
The packages
dbus,filepath, andoperatingsystemare all actively used in this file (isDarkMode,listenForSystemThemeChanges,getIconForFile,init,logPlatformInfo), so lines 322-324 are redundant. Consider removing them.🧹 Proposed cleanup
-var _ = dbus.SessionBus -var _ = filepath.Ext -var _ = operatingsystem.Info - // logPlatformInfo logs the platform information to the console🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@v3/pkg/application/application_linux.go` around lines 308 - 324, The three blank identifier assignments for dbus, filepath, and operatingsystem at the bottom of application_linux.go are redundant because those packages are already referenced by functions like isDarkMode, listenForSystemThemeChanges, getIconForFile, init, and logPlatformInfo; remove the lines "var _ = dbus.SessionBus", "var _ = filepath.Ext", and "var _ = operatingsystem.Info" so imports are no longer shadowed by useless assignments and let the compiler recognize the real usages in functions such as isVisible, getNativeApplication, and the listed theme/file/icon helpers.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@IMPLEMENTATION.md`:
- Around line 7-10: The IMPLEMENTATION.md doc is partially updated after the GTK
flip and now contains conflicting defaults and missing metadata; perform a full
consistency pass: update all occurrences that state the default stack (e.g., the
section around Line 118 and the file-reference blocks previously at Lines 374
and 392) to say "GTK4 + WebKitGTK 6.0 is the default for v3.0.0 GA" and that
"GTK3 + WebKit2GTK 4.1 is legacy opt-in via -tags gtk3 for one v3 cycle"; amend
the build constraint examples (the blocks near Lines 39–40) to include the
`!server` tag to match current server-exclusion behavior; add a dated
changelog/files-updated entry for 2026-05-16 listing files created/modified and
the flip decision, and ensure any other references to the old default are
updated to the new post-flip wording so the tracker is authoritative.
In `@v3/examples/badge-custom/build/linux/nfpm/nfpm.yaml`:
- Around line 27-29: The depends list contains incorrect Debian/Ubuntu package
names ("gtk4" and "libwebkitgtk-6.0"); update nfpm.yaml to add
distribution-specific overrides so .deb packages depend on the correct names
(use libgtk-4-1 and libwebkitgtk-6.0-4 for Debian/Ubuntu) while leaving other
distro defaults intact — modify the depends section and add a deb override
(following the pattern used in the other examples) so the deb package uses the
corrected dependency names.
In `@v3/examples/badge/build/linux/nfpm/nfpm.yaml`:
- Around line 27-29: Update the nfpm manifest so the top-level depends list does
not use non-Debian package names directly; instead follow the
distribution-specific override pattern used in the android example by replacing
or moving the generic depends entries (gtk4, libwebkitgtk-6.0) into an
overrides: deb: depends: [...] mapping with Debian/Ubuntu package names and
leaving a safe default depends array (or empty) at top-level; edit the depends
key and add an overrides -> deb block so Debian/Ubuntu packages resolve
correctly (use the android example as a template for structure and naming).
In `@v3/examples/custom-protocol-example/build/linux/nfpm/nfpm.yaml`:
- Around line 27-29: The current nfpm.yaml uses distro-incorrect generic
dependencies under the depends key (gtk4, libwebkitgtk-6.0); replace this with a
neutral/common depends list and add distribution-specific overrides like the
pattern used in v3/examples/android/build/linux/nfpm/nfpm.yaml so Debian/Ubuntu
get correct package names—update the depends section and add an overrides block
(referencing the depends key) that maps Debian/Ubuntu to their package names
(e.g., libgtk-4-1 or libwebkit2gtk-6.0-0 equivalents) so package resolution
works on Debian/Ubuntu.
In `@v3/examples/notifications/build/linux/nfpm/nfpm.yaml`:
- Around line 27-29: The depends list uses incorrect package names: replace the
generic entries under depends (gtk4, libwebkitgtk-6.0) with
distribution-appropriate package names; for Debian/Ubuntu use libgtk-4-1 and
libwebkitgtk-6.0-4, for Fedora/RHEL use gtk4 and webkitgtk6.0, and for Arch use
gtk4 and webkitgtk-6.0 (or implement a mapping strategy in nfpm.yaml per
distro). Update the depends entries accordingly so dependency resolution
succeeds.
In `@v3/pkg/application/application_linux_gtk3.go`:
- Around line 156-168: The early return after emitting the
ApplicationOpenedWithFile event causes startup handlers to be skipped; remove
the `return nil` so that after calling newApplicationEventContext(),
setOpenedWithFile(arg1) and sending to `applicationEvents` the code continues to
register the ApplicationStartup handler and invoke `setupCommonEvents()`,
`monitorThemeChanges()`, and `monitorPowerEvents()` (or, if the early-exit was
intentional, add a clear comment explaining why); locate the block that checks
`a.parent.options.FileAssociations` and modify it so the event is emitted but
normal startup flow (handlers and monitors) still runs.
- Around line 249-260: In getTheme, there's an out-of-bounds risk because
body[2] is accessed without ensuring the slice has at least 3 elements; update
the guard (and related checks) to require len(body) >= 3 before reading body[2],
and also safely type-assert body[2] to dbus.Variant and its Value() to string
(returning "", false on any failed assertion) so getTheme never panics when
given a 2-element body or unexpected types.
In `@v3/pkg/application/linux_cgo_gtk3.go`:
- Around line 569-573: The function appName calls C.g_get_application_name()
which returns GLib-owned memory that must not be freed; remove the defer
C.free(unsafe.Pointer(name)) line in appName so we don't free internal GLib
storage (C.GoString already copies the C string into Go memory), leaving appName
to simply call C.g_get_application_name(), convert with C.GoString, and return.
- Around line 697-701: clipboardGet leaks the gchar* returned by
C.gtk_clipboard_wait_for_text; after calling C.GoString(text) you must free the
C string with C.g_free to avoid the leak. Update the clipboardGet function to
check for nil (text == nil) before converting, call C.g_free(text) after
converting (or when nil not returned), and ensure no use-after-free occurs by
converting to Go string before freeing.
- Around line 460-472: The Calloc methods use value receivers so appends and
resets operate on a copy and the original pool is never updated; change the
receiver for both Calloc.String and Calloc.Free to pointer receivers (use
*Calloc) so append(c.pool, ...) and c.pool = ... modify the original struct, and
ensure Free clears the pool (e.g., set to nil or empty slice) after calling
C.free on each pointer.
- Around line 1838-1841: The zoomOut implementation uses a negative multiplier
(ZoomInFactor := -1.10) which yields a negative zoom that setZoom clamps to 1.0;
change zoomOut to use the reciprocal of the zoom-in factor (e.g., multiply
current zoom by 1.0/1.10 or compute zoomOutFactor := 1.0/ZoomInFactor) so
getZoom() * zoomOutFactor reduces zoom correctly; update the zoomOut function
(referencing zoomOut, ZoomInFactor, getZoom, setZoom) to apply a positive
reciprocal multiplier instead of a negative value.
- Around line 1095-1108: In execJS, the temporary C string created by
C.CString("") passed to webkit_web_view_evaluate_javascript is never freed,
causing a leak; replace that allocation by reusing a single preallocated empty C
string (if one exists) or explicitly free the allocation after the call—locate
the C.CString("") in execJS and either swap it for the shared empty C string
symbol or call C.free(unsafe.Pointer(...)) for that allocated pointer after
webkit_web_view_evaluate_javascript returns.
In `@v3/pkg/application/menuitem_linux_gtk3.go`:
- Around line 79-85: The setHidden implementation in linuxMenuItem incorrectly
passes the hidden flag directly to widgetSetVisible, inverting behavior; inside
linuxMenuItem.setHidden (the InvokeSync closure that calls l.blockSignal()/defer
l.unBlockSignal()), negate the boolean when calling widgetSetVisible so it
receives visibility (e.g., pass !hidden for l.native) to ensure hidden=true
makes the widget invisible.
- Around line 87-99: Remove the development stdout print from the setAccelerator
method: delete the fmt.Println("setAccelerator", accelerator) call in func (l
linuxMenuItem) setAccelerator(accelerator *accelerator) and, if runtime debug
output is desired, replace it with a proper logger call (e.g., use the project's
logging facility) guarded by a debug flag; ensure no stray fmt imports remain
after removal.
---
Nitpick comments:
In `@v3/pkg/application/application_linux.go`:
- Around line 308-324: The three blank identifier assignments for dbus,
filepath, and operatingsystem at the bottom of application_linux.go are
redundant because those packages are already referenced by functions like
isDarkMode, listenForSystemThemeChanges, getIconForFile, init, and
logPlatformInfo; remove the lines "var _ = dbus.SessionBus", "var _ =
filepath.Ext", and "var _ = operatingsystem.Info" so imports are no longer
shadowed by useless assignments and let the compiler recognize the real usages
in functions such as isVisible, getNativeApplication, and the listed
theme/file/icon helpers.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 2c780495-ec05-4fbd-a667-500580b17b8d
📒 Files selected for processing (77)
.github/workflows/build-and-test-v3.yml.github/workflows/build-cross-image.yml.github/workflows/cross-compile-test-v3.ymlAGENTS.mdIMPLEMENTATION.mddocs/src/content/docs/contributing/getting-started.mdxdocs/src/content/docs/contributing/setup.mdxdocs/src/content/docs/getting-started/installation.mdxdocs/src/content/docs/guides/build/building.mdxdocs/src/content/docs/guides/build/linux.mdxdocs/src/content/docs/guides/cli.mdxdocs/src/content/docs/quick-start/installation.mdxdocs/src/content/docs/reference/dialogs.mdxdocs/src/content/docs/reference/window.mdxv3/Taskfile.yamlv3/examples/android/build/linux/nfpm/nfpm.yamlv3/examples/badge-custom/build/linux/nfpm/nfpm.yamlv3/examples/badge/build/linux/nfpm/nfpm.yamlv3/examples/custom-protocol-example/build/linux/nfpm/nfpm.yamlv3/examples/dock/build/linux/nfpm/nfpm.yamlv3/examples/ios/build/linux/nfpm/nfpm.yamlv3/examples/notifications/build/linux/nfpm/nfpm.yamlv3/examples/webview-api-check/README.mdv3/internal/assetserver/webview/request_linux.gov3/internal/assetserver/webview/request_linux_gtk3.gov3/internal/assetserver/webview/responsewriter_linux.gov3/internal/assetserver/webview/responsewriter_linux_gtk3.gov3/internal/assetserver/webview/webkit_linux.gov3/internal/assetserver/webview/webkit_linux_gtk3.gov3/internal/capabilities/capabilities_linux.gov3/internal/capabilities/capabilities_linux_gtk3.gov3/internal/commands/updatable_build_assets/linux/nfpm/nfpm.yaml.tmplv3/internal/doctor/packagemanager/apt.gov3/internal/doctor/packagemanager/dnf.gov3/internal/doctor/packagemanager/emerge.gov3/internal/doctor/packagemanager/eopkg.gov3/internal/doctor/packagemanager/nixpkgs.gov3/internal/doctor/packagemanager/pacman.gov3/internal/doctor/packagemanager/zypper.gov3/internal/operatingsystem/webkit_linux.gov3/internal/operatingsystem/webkit_linux_gtk3.gov3/pkg/application/application_linux.gov3/pkg/application/application_linux_gtk3.gov3/pkg/application/application_linux_gtk4.gov3/pkg/application/gtkdispatch_linux.gov3/pkg/application/gtkdispatch_linux_gtk3.gov3/pkg/application/gtkdispatch_linux_gtk4.gov3/pkg/application/linux_cgo.cv3/pkg/application/linux_cgo.gov3/pkg/application/linux_cgo.hv3/pkg/application/linux_cgo_gtk3.gov3/pkg/application/linux_cgo_gtk4.gov3/pkg/application/menu_linux.gov3/pkg/application/menu_linux_gtk3.gov3/pkg/application/menu_linux_gtk4.gov3/pkg/application/menuitem_linux.gov3/pkg/application/menuitem_linux_gtk3.gov3/test/manual/dialog/bin/file-directory-gtk4v3/test/manual/dialog/bin/file-directory-gtk4-debugv3/test/manual/dialog/bin/file-directory-gtk4-racev3/test/manual/dialog/bin/file-open-gtk4v3/test/manual/dialog/bin/file-open-gtk4-racev3/test/manual/dialog/bin/file-open-multi-gtk4v3/test/manual/dialog/bin/file-open-multi-gtk4-racev3/test/manual/dialog/bin/file-save-gtk4v3/test/manual/dialog/bin/file-save-gtk4-racev3/test/manual/dialog/bin/message-error-gtk4v3/test/manual/dialog/bin/message-error-gtk4-racev3/test/manual/dialog/bin/message-info-gtk4v3/test/manual/dialog/bin/message-info-gtk4-racev3/test/manual/dialog/bin/message-question-gtk4v3/test/manual/dialog/bin/message-question-gtk4-racev3/test/manual/dialog/bin/message-warning-gtk4v3/test/manual/dialog/bin/message-warning-gtk4-racev3/tests/gtk4-benchmark/README.mdv3/tests/gtk4-benchmark/version_gtk3.gov3/tests/gtk4-benchmark/version_gtk4.go
💤 Files with no reviewable changes (4)
- v3/pkg/application/menu_linux_gtk4.go
- v3/pkg/application/application_linux_gtk4.go
- v3/pkg/application/gtkdispatch_linux_gtk4.go
- v3/pkg/application/linux_cgo_gtk4.go
| func clipboardGet() string { | ||
| clip := C.gtk_clipboard_get(C.GDK_SELECTION_CLIPBOARD) | ||
| text := C.gtk_clipboard_wait_for_text(clip) | ||
| return C.GoString(text) | ||
| } |
There was a problem hiding this comment.
Memory leak: gtk_clipboard_wait_for_text result not freed.
gtk_clipboard_wait_for_text returns a newly-allocated gchar* that must be freed with g_free().
🐛 Free the clipboard text
func clipboardGet() string {
clip := C.gtk_clipboard_get(C.GDK_SELECTION_CLIPBOARD)
text := C.gtk_clipboard_wait_for_text(clip)
+ if text == nil {
+ return ""
+ }
+ defer C.g_free(C.gpointer(text))
return C.GoString(text)
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| func clipboardGet() string { | |
| clip := C.gtk_clipboard_get(C.GDK_SELECTION_CLIPBOARD) | |
| text := C.gtk_clipboard_wait_for_text(clip) | |
| return C.GoString(text) | |
| } | |
| func clipboardGet() string { | |
| clip := C.gtk_clipboard_get(C.GDK_SELECTION_CLIPBOARD) | |
| text := C.gtk_clipboard_wait_for_text(clip) | |
| if text == nil { | |
| return "" | |
| } | |
| defer C.g_free(C.gpointer(text)) | |
| return C.GoString(text) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@v3/pkg/application/linux_cgo_gtk3.go` around lines 697 - 701, clipboardGet
leaks the gchar* returned by C.gtk_clipboard_wait_for_text; after calling
C.GoString(text) you must free the C string with C.g_free to avoid the leak.
Update the clipboardGet function to check for nil (text == nil) before
converting, call C.g_free(text) after converting (or when nil not returned), and
ensure no use-after-free occurs by converting to Go string before freeing.
There was a problem hiding this comment.
Pre-existing — clipboardGet leaking gchar* from gtk_clipboard_wait_for_text inherited from pre-flip linux_cgo.go. Tracked in #5465 as finding 4.
There was a problem hiding this comment.
@leaanthony, thanks for the context — understood, this is a pre-existing leak carried over from linux_cgo.go and is already tracked as finding 4 in #5465. I'll stop flagging it here.
✏️ Learnings added
Learnt from: leaanthony
Repo: wailsapp/wails PR: 5463
File: v3/pkg/application/linux_cgo_gtk3.go:697-701
Timestamp: 2026-05-16T02:46:21.749Z
Learning: In v3/pkg/application/linux_cgo_gtk3.go, the `clipboardGet` function leaks the `gchar*` returned by `gtk_clipboard_wait_for_text` (should be freed with `g_free`). This is a pre-existing bug inherited from the pre-flip `linux_cgo.go`, tracked in wailsapp/wails issue `#5465` (finding 4). Do not re-flag this in future reviews of this file.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: symball
Repo: wailsapp/wails PR: 4853
File: v2/internal/system/system.go:128-152
Timestamp: 2026-01-04T08:01:00.038Z
Learning: In v2/internal/system/system.go, shared functions like checkLibrary are defined without build tags but are only invoked from platform-specific files (system_linux.go, system_windows.go, system_darwin.go) that have build constraints. Reviewers should ensure there are no runtime OS checks in system.go and that platform-specific behavior is controlled via build tags. If runtime switches exist, remove them in favor of compile-time platform constraints to reduce overhead and improve correctness.
Learnt from: leaanthony
Repo: wailsapp/wails PR: 4906
File: v3/internal/setupwizard/wizard_windows.go:93-94
Timestamp: 2026-01-26T01:56:49.314Z
Learning: Ensure the Go toolchain minimum version for Wails v3 is 1.25+. Update go.mod to reflect 1.25+ and validate that setup wizard checks enforce Go 1.25+ at release time. Align any CI/go-version checks, documentation, and release notes with this requirement; this guideline applies to all Go files under the v3 module, not just the wizard.
| func (w *linuxWebviewWindow) execJS(js string) { | ||
| InvokeAsync(func() { | ||
| value := C.CString(js) | ||
| C.webkit_web_view_evaluate_javascript(w.webKitWebView(), | ||
| value, | ||
| C.long(len(js)), | ||
| nil, | ||
| C.CString(""), | ||
| nil, | ||
| nil, | ||
| nil) | ||
| C.free(unsafe.Pointer(value)) | ||
| }) | ||
| } |
There was a problem hiding this comment.
Memory leak: empty C string in execJS never freed.
Line 1102 creates C.CString("") which is never freed, leaking memory on every execJS call.
🐛 Use the preallocated empty string or free it
func (w *linuxWebviewWindow) execJS(js string) {
InvokeAsync(func() {
value := C.CString(js)
+ defer C.free(unsafe.Pointer(value))
C.webkit_web_view_evaluate_javascript(w.webKitWebView(),
value,
C.long(len(js)),
nil,
- C.CString(""),
+ emptyWorldName,
nil,
nil,
nil)
- C.free(unsafe.Pointer(value))
})
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@v3/pkg/application/linux_cgo_gtk3.go` around lines 1095 - 1108, In execJS,
the temporary C string created by C.CString("") passed to
webkit_web_view_evaluate_javascript is never freed, causing a leak; replace that
allocation by reusing a single preallocated empty C string (if one exists) or
explicitly free the allocation after the call—locate the C.CString("") in execJS
and either swap it for the shared empty C string symbol or call
C.free(unsafe.Pointer(...)) for that allocated pointer after
webkit_web_view_evaluate_javascript returns.
There was a problem hiding this comment.
Pre-existing — execJS leaking C.CString("") inherited from pre-flip linux_cgo.go. Tracked in #5465 as finding 7.
There was a problem hiding this comment.
@leaanthony, understood — the C.CString("") leak predates this PR and is already captured in #5465 (finding 7). No action needed here. Would you like me to resolve this review comment since it's tracked upstream?
🧠 Learnings used
Learnt from: symball
Repo: wailsapp/wails PR: 4853
File: v2/internal/system/system.go:128-152
Timestamp: 2026-01-04T08:01:00.038Z
Learning: In v2/internal/system/system.go, shared functions like checkLibrary are defined without build tags but are only invoked from platform-specific files (system_linux.go, system_windows.go, system_darwin.go) that have build constraints. Reviewers should ensure there are no runtime OS checks in system.go and that platform-specific behavior is controlled via build tags. If runtime switches exist, remove them in favor of compile-time platform constraints to reduce overhead and improve correctness.
Learnt from: leaanthony
Repo: wailsapp/wails PR: 4906
File: v3/internal/setupwizard/wizard_windows.go:93-94
Timestamp: 2026-01-26T01:56:49.314Z
Learning: Ensure the Go toolchain minimum version for Wails v3 is 1.25+. Update go.mod to reflect 1.25+ and validate that setup wizard checks enforce Go 1.25+ at release time. Align any CI/go-version checks, documentation, and release notes with this requirement; this guideline applies to all Go files under the v3 module, not just the wizard.
| func (w *linuxWebviewWindow) zoomOut() { | ||
| ZoomInFactor := -1.10 | ||
| w.setZoom(w.getZoom() * ZoomInFactor) | ||
| } |
There was a problem hiding this comment.
zoomOut is broken: negative multiplier always clamps to 1.0.
ZoomInFactor := -1.10 produces a negative zoom value, which setZoom clamps to 1.0. Zoom out effectively resets zoom instead of reducing it.
🐛 Use reciprocal factor for zoom out
func (w *linuxWebviewWindow) zoomOut() {
- ZoomInFactor := -1.10
- w.setZoom(w.getZoom() * ZoomInFactor)
+ ZoomOutFactor := 1.0 / 1.10
+ w.setZoom(w.getZoom() * ZoomOutFactor)
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| func (w *linuxWebviewWindow) zoomOut() { | |
| ZoomInFactor := -1.10 | |
| w.setZoom(w.getZoom() * ZoomInFactor) | |
| } | |
| func (w *linuxWebviewWindow) zoomOut() { | |
| ZoomOutFactor := 1.0 / 1.10 | |
| w.setZoom(w.getZoom() * ZoomOutFactor) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@v3/pkg/application/linux_cgo_gtk3.go` around lines 1838 - 1841, The zoomOut
implementation uses a negative multiplier (ZoomInFactor := -1.10) which yields a
negative zoom that setZoom clamps to 1.0; change zoomOut to use the reciprocal
of the zoom-in factor (e.g., multiply current zoom by 1.0/1.10 or compute
zoomOutFactor := 1.0/ZoomInFactor) so getZoom() * zoomOutFactor reduces zoom
correctly; update the zoomOut function (referencing zoomOut, ZoomInFactor,
getZoom, setZoom) to apply a positive reciprocal multiplier instead of a
negative value.
There was a problem hiding this comment.
Pre-existing — zoomOut using negative multiplier inherited from pre-flip linux_cgo.go. Tracked in #5465 as finding 6. (Probably user-visible if someone calls zoomOut — they get clamp-to-1.0 instead of zoom-out.)
There was a problem hiding this comment.
@leaanthony Thanks for the context — good to know it predates this flip and is already captured in #5465 (finding 6). I'll leave this comment open until the fix lands there. The user-visible impact (zoom-out silently resetting to 1.0x) makes it worth prioritising in that follow-up.
🧠 Learnings used
Learnt from: symball
Repo: wailsapp/wails PR: 4853
File: v2/internal/system/system.go:128-152
Timestamp: 2026-01-04T08:01:00.038Z
Learning: In v2/internal/system/system.go, shared functions like checkLibrary are defined without build tags but are only invoked from platform-specific files (system_linux.go, system_windows.go, system_darwin.go) that have build constraints. Reviewers should ensure there are no runtime OS checks in system.go and that platform-specific behavior is controlled via build tags. If runtime switches exist, remove them in favor of compile-time platform constraints to reduce overhead and improve correctness.
Learnt from: leaanthony
Repo: wailsapp/wails PR: 4906
File: v3/internal/setupwizard/wizard_windows.go:93-94
Timestamp: 2026-01-26T01:56:49.314Z
Learning: Ensure the Go toolchain minimum version for Wails v3 is 1.25+. Update go.mod to reflect 1.25+ and validate that setup wizard checks enforce Go 1.25+ at release time. Align any CI/go-version checks, documentation, and release notes with this requirement; this guideline applies to all Go files under the v3 module, not just the wizard.
| func (l linuxMenuItem) setHidden(hidden bool) { | ||
| InvokeSync(func() { | ||
| menuItemSetHidden(l, hidden) | ||
| l.blockSignal() | ||
| defer l.unBlockSignal() | ||
| widgetSetVisible(l.native, hidden) | ||
| }) | ||
| l.isHidden = hidden | ||
| } |
There was a problem hiding this comment.
Inverted visibility logic.
widgetSetVisible(l.native, hidden) passes hidden as the visibility parameter. If hidden=true, this makes the widget visible (opposite of intended behavior). The parameter should be negated.
🐛 Proposed fix
func (l linuxMenuItem) setHidden(hidden bool) {
InvokeSync(func() {
l.blockSignal()
defer l.unBlockSignal()
- widgetSetVisible(l.native, hidden)
+ widgetSetVisible(l.native, !hidden)
})
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| func (l linuxMenuItem) setHidden(hidden bool) { | |
| InvokeSync(func() { | |
| menuItemSetHidden(l, hidden) | |
| l.blockSignal() | |
| defer l.unBlockSignal() | |
| widgetSetVisible(l.native, hidden) | |
| }) | |
| l.isHidden = hidden | |
| } | |
| func (l linuxMenuItem) setHidden(hidden bool) { | |
| InvokeSync(func() { | |
| l.blockSignal() | |
| defer l.unBlockSignal() | |
| widgetSetVisible(l.native, !hidden) | |
| }) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@v3/pkg/application/menuitem_linux_gtk3.go` around lines 79 - 85, The
setHidden implementation in linuxMenuItem incorrectly passes the hidden flag
directly to widgetSetVisible, inverting behavior; inside linuxMenuItem.setHidden
(the InvokeSync closure that calls l.blockSignal()/defer l.unBlockSignal()),
negate the boolean when calling widgetSetVisible so it receives visibility
(e.g., pass !hidden for l.native) to ensure hidden=true makes the widget
invisible.
There was a problem hiding this comment.
Pre-existing — setHidden passing the hidden flag directly to widgetSetVisible (should negate) inherited from pre-flip menuitem_linux.go. Tracked in #5465 as finding 8. User-visible: MenuItem.SetHidden(true) makes the item visible.
There was a problem hiding this comment.
@leaanthony, thanks for the context. Acknowledged — this is a pre-existing inversion inherited from the pre-flip menuitem_linux.go, not introduced by this PR, and it's already tracked in #5465 (finding 8). I'll note this for future reviews.
✏️ Learnings added
Learnt from: leaanthony
Repo: wailsapp/wails PR: 5463
File: v3/pkg/application/menuitem_linux_gtk3.go:79-85
Timestamp: 2026-05-16T02:46:26.614Z
Learning: In `v3/pkg/application/menuitem_linux_gtk3.go` (Go, Wails v3 Linux GTK3 backend), the `setHidden` method has a pre-existing bug where `widgetSetVisible(l.native, hidden)` passes `hidden` directly instead of `!hidden`, causing `MenuItem.SetHidden(true)` to make the item visible (inverted behavior). This bug was inherited from the pre-GTK4-flip `menuitem_linux.go` and is tracked in issue `#5465` (finding 8). Do not re-flag this as a new issue in future reviews of this file.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: symball
Repo: wailsapp/wails PR: 4853
File: v2/internal/system/system.go:128-152
Timestamp: 2026-01-04T08:01:00.038Z
Learning: In v2/internal/system/system.go, shared functions like checkLibrary are defined without build tags but are only invoked from platform-specific files (system_linux.go, system_windows.go, system_darwin.go) that have build constraints. Reviewers should ensure there are no runtime OS checks in system.go and that platform-specific behavior is controlled via build tags. If runtime switches exist, remove them in favor of compile-time platform constraints to reduce overhead and improve correctness.
Learnt from: leaanthony
Repo: wailsapp/wails PR: 4906
File: v3/internal/setupwizard/wizard_windows.go:93-94
Timestamp: 2026-01-26T01:56:49.314Z
Learning: Ensure the Go toolchain minimum version for Wails v3 is 1.25+. Update go.mod to reflect 1.25+ and validate that setup wizard checks enforce Go 1.25+ at release time. Align any CI/go-version checks, documentation, and release notes with this requirement; this guideline applies to all Go files under the v3 module, not just the wizard.
- application_linux.go: remove the three unnecessary `var _ = ...` blank-identifier assignments at lines 308-324. dbus, filepath, and operatingsystem are all actually used by isDarkMode, listenForSystemThemeChanges, getIconForFile, and init — the blank assignments shadowed nothing. - IMPLEMENTATION.md: update Decision 1.1's Build Tags block to reflect the !server addition from de9b677 (review-feedback round 1). Both default and legacy constraints now show && !server, with a note explaining server mode excludes both paths. - Four example nfpm.yaml files (badge, badge-custom, custom-protocol-example, notifications) had top-level depends entries using Arch-style names (gtk4 / libwebkitgtk-6.0) which are not valid Debian/Ubuntu package names. Restructured to match the android/dock/ios/nfpm.yaml.tmpl pattern: Debian names at top-level (libgtk-4-1, libwebkitgtk-6.0-4) plus per-format overrides for rpm (gtk4, webkitgtk6.0) and archlinux (gtk4, webkitgtk-6.0). Refs #5459, PR #5463, CodeRabbit review.
|
CodeRabbit round — all 14 actionable + 1 nitpick addressed. Pushed 1629542. Fixed in 1629542 (5 comments)
Deferred to #5465 (9 comments — all pre-existing in master)All 9 are bugs in the
All affect the legacy Re-verification on lin-node1 (Ubuntu 26.04)
The blank-identifier removal in Follow-up issues filed by this PR's reviews
|
…t-flip # Conflicts: # docs/src/content/docs/contributing/getting-started.mdx # docs/src/content/docs/contributing/setup.mdx
CodeRabbit re-review found two stale sections in IMPLEMENTATION.md that I missed in the first pass (only updated Decision 1.1's Build Tags block at the top, not the rest of the doc): - Line 119: Package key naming convention comment still listed gtk3 / webkit2gtk-4.1 as primary/default and gtk4 / webkitgtk-6.0 as experimental. Inverted to reflect the post-flip polarity. - Lines 375-408: Files Reference section was titled "GTK3 (Default) Files" and "GTK4 (Experimental) Files" and listed filenames that this PR deleted (linux_cgo_gtk4.go, application_linux_gtk4.go, webkit6.go, etc.). Rewrote both blocks to describe the post-flip layout: GTK4 default files (no tag) and GTK3 legacy files (-tags gtk3). Added an explicit "Historical note" pointing out that the Phase tracker blocks earlier in the doc intentionally retain pre-flip filenames as a record of work done at the time. Refs #5463, CodeRabbit follow-up at #discussion_r3251879633.
Cluster of pre-existing bugs in the legacy GTK3 implementation files (now `*_gtk3.go` after #5463). Surfaced by CodeRabbit on #5463; the file rename made them visible but the bugs themselves predate the default-flip. All affect the `-tags gtk3` build path only. application_linux_gtk3.go - run(): drop the early `return nil` on the file-association branch so startup handlers, common event setup, theme/power monitoring, and the GTK main loop still run after `ApplicationOpenedWithFile` is emitted. Restructure the surrounding `else` so the "not a URL, potential file open?" debug log no longer fires after a successful file-association match. - getTheme(): guard `body[2]` access with `len(body) >= 3` and use comma-ok type assertions for `dbus.Variant` and the inner `string`, returning `("", false)` on any mismatch instead of panicking. linux_cgo_gtk3.go - appName(): drop the `defer C.free` on the pointer returned by `g_get_application_name()`. That memory belongs to GLib internal storage; `C.GoString` already copies into Go memory. - clipboardGet(): nil-check the `gchar*` returned by `gtk_clipboard_wait_for_text` and `g_free` it after copying into a Go string. Previously leaked on every call. - Calloc.String / Calloc.Free: change to pointer receivers so the `append(c.pool, ...)` actually grows the original pool. With value receivers the pool stayed empty and Free was a no-op, leaking every `c.String(...)` allocation. - zoomIn / zoomOut: drop the negative `-1.10` multiplier (which `setZoom` then clamped to 1.0) and use the reciprocal of `zoomInFactor` for zoomOut. Promoted the factor to a package-level const and removed the stale "FIXME: assumed to be incorrect" comment. - execJS: reuse the file-level `emptyWorldName` C string instead of allocating a fresh `C.CString("")` per call that was never freed. menuitem_linux_gtk3.go - setHidden: pass `!hidden` to `widgetSetVisible` (previously inverted; hiding a menu item showed it and vice versa). - setAccelerator: drop the development `fmt.Println("setAccelerator", ...)`. The identical `Calloc` value-receiver bug also exists verbatim in `linux_cgo.go` (the now-default GTK4 path); intentionally left for a follow-up to keep this PR scoped to the gtk3 tracking issue. Refs #5465
) * fix(v3/linux/gtk3): resolve pre-existing bugs in legacy gtk3 path Cluster of pre-existing bugs in the legacy GTK3 implementation files (now `*_gtk3.go` after #5463). Surfaced by CodeRabbit on #5463; the file rename made them visible but the bugs themselves predate the default-flip. All affect the `-tags gtk3` build path only. application_linux_gtk3.go - run(): drop the early `return nil` on the file-association branch so startup handlers, common event setup, theme/power monitoring, and the GTK main loop still run after `ApplicationOpenedWithFile` is emitted. Restructure the surrounding `else` so the "not a URL, potential file open?" debug log no longer fires after a successful file-association match. - getTheme(): guard `body[2]` access with `len(body) >= 3` and use comma-ok type assertions for `dbus.Variant` and the inner `string`, returning `("", false)` on any mismatch instead of panicking. linux_cgo_gtk3.go - appName(): drop the `defer C.free` on the pointer returned by `g_get_application_name()`. That memory belongs to GLib internal storage; `C.GoString` already copies into Go memory. - clipboardGet(): nil-check the `gchar*` returned by `gtk_clipboard_wait_for_text` and `g_free` it after copying into a Go string. Previously leaked on every call. - Calloc.String / Calloc.Free: change to pointer receivers so the `append(c.pool, ...)` actually grows the original pool. With value receivers the pool stayed empty and Free was a no-op, leaking every `c.String(...)` allocation. - zoomIn / zoomOut: drop the negative `-1.10` multiplier (which `setZoom` then clamped to 1.0) and use the reciprocal of `zoomInFactor` for zoomOut. Promoted the factor to a package-level const and removed the stale "FIXME: assumed to be incorrect" comment. - execJS: reuse the file-level `emptyWorldName` C string instead of allocating a fresh `C.CString("")` per call that was never freed. menuitem_linux_gtk3.go - setHidden: pass `!hidden` to `widgetSetVisible` (previously inverted; hiding a menu item showed it and vice versa). - setAccelerator: drop the development `fmt.Println("setAccelerator", ...)`. The identical `Calloc` value-receiver bug also exists verbatim in `linux_cgo.go` (the now-default GTK4 path); intentionally left for a follow-up to keep this PR scoped to the gtk3 tracking issue. Refs #5465 * fix(v3/linux/gtk3): address Copilot review on #5466 - Revert setHidden in menuitem_linux_gtk3.go: widgetSetVisible takes a `hidden` flag (true → gtk_widget_hide, false → gtk_widget_show) — the same convention as the GTK4 (linux_cgo.go) and purego (linux_purego.go) implementations. The original `widgetSetVisible(l.native, hidden)` was correct; the negation introduced in the previous commit inverted behaviour. Bug-bash item #8 in #5465 misread the function name. - Make NewCalloc return *Calloc to match the pointer-receiver String/Free so the API is consistently pointer-semantic and chained calls like `NewCalloc().String(...)` continue to compile. Existing call sites (`c := NewCalloc(); defer c.Free()`) are unchanged. - Update UNRELEASED_CHANGELOG.md accordingly: drop the (incorrect) setHidden line, note the NewCalloc return-type change. Refs #5466 review (Copilot). * fix(v3/linux): apply Calloc value-receiver fix to the default GTK4 path Mirror the same Calloc fix from linux_cgo_gtk3.go in linux_cgo.go (the now-default GTK4 build). Without pointer receivers, `append(c.pool, ...)` in `String` mutated a copy, so the pool stayed empty and `Free()` was a no-op — every per-window `c.String(...)` allocation in `setupSignalHandlers` and `windowNewWebview` leaked. With value receivers gone, allocations are tracked and released on Free. `NewCalloc` now returns `*Calloc` so the API is consistently pointer-semantic across both build tags. Refs #5466 review (Copilot).
#5474) (#5477) * fix(v3/linux): wire common events + dbus monitors on GTK4 default path (#5474) The GTK4 default build's `linuxApp.run()` (the post-#5463 default in alpha.93) never called `setupCommonEvents()`, `monitorThemeChanges()`, or `monitorPowerEvents()`. As a result, listeners registered for `events.Common.ApplicationStarted`, `Common.ThemeChanged`, `Common.SystemWillSleep` and `Common.SystemDidWake` never fired, since nothing forwarded the underlying `events.Linux.*` events to their common counterparts. Reverting to alpha.92 worked because the gtk3 default already wired these in `application_linux_gtk3.go` (renamed from the previous `application_linux.go`). Restore parity by calling all three from the gtk4 `run()`, and extract the two dbus monitor helpers to a build-tag-shared `application_linux_dbus.go` so both stacks use the same implementation. Verified with the existing `pkg/application/internal/tests/services/*` suite on lin-node1: the startup/shutdown tests hang under the pre-fix GTK4 default (`Common.ApplicationStarted` never fires, listener never calls `app.Quit()`) and pass after the fix on both default and `-tags gtk3` builds. * fix(v3): address review on #5477 - application_linux.go run(): drop a.monitorThemeChanges() — the GTK4 default already has go listenForSystemThemeChanges(a) running from init(), which uses the portal-standard org.freedesktop.appearance namespace, so calling both would double-fire Common.ThemeChanged. monitorThemeChanges() stays in the shared dbus file because GTK3 still uses it. Updates the changelog to reflect that only the power-monitor helper is newly shared. - application_linux.go isDarkMode(): type-check result.Value().(dbus.Variant) instead of an unchecked assertion that would panic on unexpected portal payload shapes. - application_linux_dbus.go monitorThemeChanges(): replace panic(err) on AddMatchSignal failure with the same warning-and-return pattern used by the surrounding dbus setup, so a session-bus policy error disables theme monitoring instead of killing the app.
Resolve conflicts from the GTK4-default flip (#5463): - Apply execJS additions in setResizable/setFrameless to the renamed linux_cgo.go (GTK4) and linux_cgo_gtk3.go (GTK3); drop the deleted linux_cgo_gtk4.go - Regenerate bundled runtime.js/runtime.debug.js from merged drag.ts
Fixes #5459.
For v3.0.0 GA, GTK4 + WebKitGTK 6.0 becomes the default Linux build stack. GTK3 + WebKit2GTK 4.1 becomes a legacy opt-in via
-tags gtk3for one v3 cycle and is scheduled for removal in v3.1. Rationale recorded inIMPLEMENTATION.mdDecision 1.1.Summary of changes
v3/renamed from*_linux_gtk4.go→*_linux.go(default), constraintgtk4→!gtk3. 10 files renamed from*_linux.go→*_linux_gtk3.go(legacy), constraint!gtk4→gtk3. Thegtk4build tag is retired in favor ofgtk3as the toggle.linux_cgo_gtk4.c/.h→linux_cgo.c/.h. Build directives,#includedirective, and header guards updated to match the new filename — these would have silently mismatched the cgo pair and produced link errors if missed.internal/doctor/packagemanager/*.go(7 files): inverted required/optional polarity.pkg/doctor-ng/packagemanager/*.goalready had the correct polarity — left alone.build-and-test-v3.yml,cross-compile-test-v3.yml,build-cross-image.yml: both stacks installed; step labels renamedGTK4 default/GTK3 legacy;BUILD_TAGS=gtk4→=gtk3;-tags gtk4→-tags gtk3; library-presence test checks GTK4 SOs first.v3/Taskfile.yamlrenametest:example:linux:gtk4→:gtk3,sanity:gtk4→:gtk3, hints flipped. User-template Taskfiles unchanged (already passEXTRA_TAGSgenerically).updatable_build_assets/linux/nfpm/nfpm.yaml.tmpl: default runtime deps →libgtk-4-1/libwebkitgtk-6.0-4; RPM and Arch overrides updated; legacy deps shown commented out for users who build with-tags gtk3. All 7 examplenfpm.yamlfiles bumped to match.linux.mdx"GTK4 Support (Experimental)" → "Legacy GTK3 Support";building.mdx,cli.mdx,dialogs.mdx,window.mdx, bothinstallation.mdxs, bothcontributing/*.mdxs updated. Anchor renames:#gtk4-support-experimental→#legacy-gtk3-support,#linux-gtk4-limitations→#linux-dialog-behavior. No orphaned inbound links.IMPLEMENTATION.mdgets Decision 1.1 (2026-05-16); original Decision 1 preserved and marked SUPERSEDED.AGENTS.mdpolicy section updated.v3/test/manual/dialog/bin/file-*-gtk4*andmessage-*-gtk4*test binaries committed during the original #4958 GTK4 dev work.Reviewer hot-spots — please look here first
-skip "TestService"CI skip moved tracks. Originally it was on the-tags gtk4opt-in step (display issues in CI). Since GTK4 is now default, the skip moves to the default-test step; the-tags gtk3legacy step now runs the full suite. See.github/workflows/build-and-test-v3.ymllines ~170-179.fmt.Printlnblock inapplication_linux.goinit()printing the experimental box on every app startup is deleted — GTK4 is no longer experimental.message-*-gtk4*binaries. The original plan only mentionedfile-*-gtk4*; I also removed the symmetricmessage-*-gtk4*binaries.icon lookup not implemented for GTK4error rephrased to point users at-tags gtk3as the workaround, since this is now reachable on the default path.Verification status
go vet ./...on darwininternal/generator/testcasesare unrelated.)CGO_ENABLED=0 GOOS=linuxlin-node1(or any Linux box withlibgtk-4-dev libwebkitgtk-6.0-dev libgtk-3-dev libwebkit2gtk-4.1-devinstalled). At minimum:cd v3 && go build ./...(default GTK4) andcd v3 && go build -tags gtk3 ./...(legacy).libgtk-4-1andlibwebkitgtk-6.0-4for Debian/Ubuntu based on standard naming; pleaseapt-cache show libwebkitgtk-6.0-4onlin-node1to confirm before the resulting.debships. If the actual package name differs, the generated package won't install.Downstream packager migration paragraph (for
v3.0.0-beta.1release notes)Out of scope
wails3 build(e.g. detect GTK3-only host and auto-inject-tags gtk3) — explicitly chosen against for consistency; users on a GTK3-only host get the barepkg-config webkitgtk-6.0failure with a clear error pointing at-tags gtk3.gtk4-benchmark/directory (kept by request — it's a dev tool that compares both stacks).ja/,ru/,zh-cn/,pt/,zh-tw/,de/,ko/,fr/) — will sync via Crowdin.Test plan
lin-node1(or equivalent):cd v3 && go build ./...succeeds (default GTK4) withlibgtk-4-dev libwebkitgtk-6.0-devinstalledlin-node1:cd v3 && go build -tags gtk3 ./...succeeds withlibgtk-3-dev libwebkit2gtk-4.1-devinstalledwails3 doctorreports GTK4/WebKitGTK 6.0 as required, GTK3/WebKit2GTK 4.1 as(legacy)optionalwails3 doctor-ngpolarity matches (unchanged file — sanity check)wails3 build(default) and one withwails3 build -tags gtk3, run bothapt-cache show libwebkitgtk-6.0-4returns a real package on Ubuntu 24.04 / Debian 13 (otherwise adjust nfpm template runtime dep names)Summary by CodeRabbit
Documentation
Chores
Packaging / Examples
Behavior / Refactor