Skip to content

feat(linux): flip GTK4 + WebKitGTK 6.0 to the default build (#5459)#5463

Merged
leaanthony merged 5 commits into
masterfrom
feature/gtk4-default-flip
May 16, 2026
Merged

feat(linux): flip GTK4 + WebKitGTK 6.0 to the default build (#5459)#5463
leaanthony merged 5 commits into
masterfrom
feature/gtk4-default-flip

Conversation

@leaanthony

@leaanthony leaanthony commented May 16, 2026

Copy link
Copy Markdown
Member

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 gtk3 for one v3 cycle and is scheduled for removal in v3.1. Rationale recorded in IMPLEMENTATION.md Decision 1.1.

Summary of changes

Area What changed
Build constraints 12 files in v3/ renamed from *_linux_gtk4.go*_linux.go (default), constraint gtk4!gtk3. 10 files renamed from *_linux.go*_linux_gtk3.go (legacy), constraint !gtk4gtk3. The gtk4 build tag is retired in favor of gtk3 as the toggle.
cgo C/H files linux_cgo_gtk4.c/.hlinux_cgo.c/.h. Build directives, #include directive, and header guards updated to match the new filename — these would have silently mismatched the cgo pair and produced link errors if missed.
Doctor Legacy internal/doctor/packagemanager/*.go (7 files): inverted required/optional polarity. pkg/doctor-ng/packagemanager/*.go already had the correct polarity — left alone.
CI build-and-test-v3.yml, cross-compile-test-v3.yml, build-cross-image.yml: both stacks installed; step labels renamed GTK4 default / GTK3 legacy; BUILD_TAGS=gtk4=gtk3; -tags gtk4-tags gtk3; library-presence test checks GTK4 SOs first.
Taskfile v3/Taskfile.yaml rename test:example:linux:gtk4:gtk3, sanity:gtk4:gtk3, hints flipped. User-template Taskfiles unchanged (already pass EXTRA_TAGS generically).
nfpm template 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 example nfpm.yaml files bumped to match.
Docs English canonical only (Crowdin sync handles i18n): linux.mdx "GTK4 Support (Experimental)" → "Legacy GTK3 Support"; building.mdx, cli.mdx, dialogs.mdx, window.mdx, both installation.mdxs, both contributing/*.mdxs updated. Anchor renames: #gtk4-support-experimental#legacy-gtk3-support, #linux-gtk4-limitations#linux-dialog-behavior. No orphaned inbound links.
Tracking docs IMPLEMENTATION.md gets Decision 1.1 (2026-05-16); original Decision 1 preserved and marked SUPERSEDED. AGENTS.md policy section updated.
Cleanup Removed v3/test/manual/dialog/bin/file-*-gtk4* and message-*-gtk4* test binaries committed during the original #4958 GTK4 dev work.

Reviewer hot-spots — please look here first

  1. The -skip "TestService" CI skip moved tracks. Originally it was on the -tags gtk4 opt-in step (display issues in CI). Since GTK4 is now default, the skip moves to the default-test step; the -tags gtk3 legacy step now runs the full suite. See .github/workflows/build-and-test-v3.yml lines ~170-179.
  2. The "GTK4 EXPERIMENTAL" stdout banner is removed. The fmt.Println block in application_linux.go init() printing the experimental box on every app startup is deleted — GTK4 is no longer experimental.
  3. Beyond-plan deletion of message-*-gtk4* binaries. The original plan only mentioned file-*-gtk4*; I also removed the symmetric message-*-gtk4* binaries.
  4. icon lookup not implemented for GTK4 error rephrased to point users at -tags gtk3 as the workaround, since this is now reachable on the default path.

Verification status

Status
go vet ./... on darwin ✅ Clean against this change. (Pre-existing JSON-tag / MarshalJSON issues in internal/generator/testcases are unrelated.)
Cross-vet CGO_ENABLED=0 GOOS=linux Predictably fails — the package mixes cgo and non-cgo Linux files; same on master.
Linux cgo build on a real host Not done — required gate before merge. Test on lin-node1 (or any Linux box with libgtk-4-dev libwebkitgtk-6.0-dev libgtk-3-dev libwebkit2gtk-4.1-dev installed). At minimum: cd v3 && go build ./... (default GTK4) and cd v3 && go build -tags gtk3 ./... (legacy).
nfpm runtime package names exist on target distros ⚠️ Picked libgtk-4-1 and libwebkitgtk-6.0-4 for Debian/Ubuntu based on standard naming; please apt-cache show libwebkitgtk-6.0-4 on lin-node1 to confirm before the resulting .deb ships. If the actual package name differs, the generated package won't install.

Downstream packager migration paragraph (for v3.0.0-beta.1 release notes)

Linux: default toolchain is now GTK4 + WebKitGTK 6.0. Packagers for Flatpak, AUR, nixpkgs, Debian, Fedora, and other distributions should: (1) drop -tags gtk4 from any existing build invocations — it is now a no-op. (2) Replace build-time system dependencies libgtk-3-dev / libwebkit2gtk-4.1-dev with libgtk-4-dev / libwebkitgtk-6.0-dev (Debian/Ubuntu naming; equivalents: gtk4-devel/webkitgtk6.0-devel on Fedora; gtk4/webkitgtk-6.0 on Arch). (3) If you target a stable distribution that ships only GTK3 — Ubuntu 22.04 LTS, Debian 12, Fedora 39 or older, RHEL 9.x — add -tags gtk3 to your build command. The legacy path is supported through the v3.0.x line and scheduled for removal in v3.1; plan to migrate to GTK4 in coordination with your distribution's GTK4 / WebKitGTK 6.0 availability. The wails3 doctor and wails3 doctor-ng commands now report GTK4 as required and GTK3 as (legacy) optional; the wails3 tool capabilities JSON output is unchanged. No source code changes are required in Wails applications themselves.

Out of scope

  • Removal of the GTK3 code path entirely — that's v3.1 work.
  • Smart-default auto-fallback in 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 bare pkg-config webkitgtk-6.0 failure with a clear error pointing at -tags gtk3.
  • Renaming the gtk4-benchmark/ directory (kept by request — it's a dev tool that compares both stacks).
  • i18n docs trees (ja/, ru/, zh-cn/, pt/, zh-tw/, de/, ko/, fr/) — will sync via Crowdin.
  • v2 maintenance.

Test plan

  • On lin-node1 (or equivalent): cd v3 && go build ./... succeeds (default GTK4) with libgtk-4-dev libwebkitgtk-6.0-dev installed
  • On lin-node1: cd v3 && go build -tags gtk3 ./... succeeds with libgtk-3-dev libwebkit2gtk-4.1-dev installed
  • wails3 doctor reports GTK4/WebKitGTK 6.0 as required, GTK3/WebKit2GTK 4.1 as (legacy) optional
  • wails3 doctor-ng polarity matches (unchanged file — sanity check)
  • Build one example with wails3 build (default) and one with wails3 build -tags gtk3, run both
  • Verify apt-cache show libwebkitgtk-6.0-4 returns a real package on Ubuntu 24.04 / Debian 13 (otherwise adjust nfpm template runtime dep names)
  • CI green for the v3 workflows on this PR

Summary by CodeRabbit

  • Documentation

    • Linux guides, getting-started and installation updated: GTK4 + WebKitGTK 6.0 is now the default; legacy GTK3 + WebKit2GTK 4.1 is opt-in via wails3 build -tags gtk3 (supported through v3.0.x). Added minimum-distro guidance, doctor command updates, build/tag examples, and feature-difference notes.
  • Chores

    • CI workflows updated to run explicit GTK4-default and GTK3-legacy test/build paths.
  • Packaging / Examples

    • Example package manifests and templates now default to GTK4/WebKitGTK 6.0 with legacy GTK3 overrides.
  • Behavior / Refactor

    • Linux platform backend and menu/dialog handling reworked to reflect the GTK4-default / GTK3-legacy split; dialog/menu behaviors and environment reporting clarified.

Review Change Stack

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.
Copilot AI review requested due to automatic review settings May 16, 2026 01:27
@leaanthony leaanthony added this to the v3.0.0-beta.1 milestone May 16, 2026
@coderabbitai

coderabbitai Bot commented May 16, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c5dd8ecf-5490-45fc-b7d3-c6da21e5c846

📥 Commits

Reviewing files that changed from the base of the PR and between ccd049e and 3d2113b.

📒 Files selected for processing (1)
  • IMPLEMENTATION.md

Walkthrough

This PR flips the Linux default to GTK4 + WebKitGTK 6.0 (no build tag) and makes GTK3 + WebKit2GTK 4.1 a legacy opt-in via -tags gtk3, updating CI, docs, Taskfile/nfpm, doctor maps, CGO/webview files, Linux app backends, menu/dispatch, and tests.

Changes

GTK4 + WebKitGTK 6.0 Default Flip

Layer / File(s) Summary
All changed checkpoints
...
Aggregate changes implementing the GTK4-default / GTK3-legacy flip across CI workflows, documentation, Taskfile and nfpm templates, package-manager doctor mappings, CGO/webview build-tag swaps and new GTK3 implementations, Linux application backend refactor, menu/menuitem/dispatch updates, and related tests.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

  • #4339: Overlaps on nfpm manifests and doctor package-manager mapping updates for GTK/WebKit distro dependencies.
  • #5464: Related to menu processing changes; the new processed guard may explain Menu.Update() behavior in that issue.
  • #5465: Shares goal and file-level changes for flipping GTK4/WebKitGTK 6.0 to default and exposing gtk3-tagged files.

Possibly related PRs

Suggested labels

Linux, Enhancement, Documentation, cli, templates, go, v3, Implemented in v3, size:XXL

Suggested reviewers

  • atterpac
  • ndianabasi

"🐇 I hopped through the flip with glee,
Swapped tags and docs beneath the tree.
WebKit six leads the default song,
GTK3 lingers, tagged but strong.
CI, packages, menus — all agree."

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/gtk4-default-flip

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread v3/pkg/application/application_linux.go Outdated
Comment thread v3/pkg/application/linux_cgo.go Outdated
Comment thread v3/pkg/application/menu_linux.go Outdated
Comment on lines +37 to +42
impl := menu.impl.(*linuxMenu)
if impl.processed {
// Menu already processed, skip re-processing to avoid duplicates
return
}
impl.processed = true

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up issue: #5464.

Comment thread v3/pkg/application/menuitem_linux.go Outdated
- 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.
@leaanthony

Copy link
Copy Markdown
Member Author

Pushed de9b677 addressing the review feedback. Summary per comment:

Comment Status Fix
application_linux.go:1 — missing !server (#discussion_r3251765537) ✅ Fixed Added && !server. The asymmetry was pre-existing in the original _gtk4.go file and got carried through the rename.
linux_cgo.go:1 — missing !server (#discussion_r3251765566) ✅ Fixed Same. Also added to linux_cgo.c and linux_cgo.h so the cgo pair stays mated under -tags server.
menu_linux.go:1 — missing !server (#discussion_r3251765574) ✅ Fixed Now linux && !android && !gtk3 && !server.
menuitem_linux.go:1 — missing !server (#discussion_r3251765587) ✅ Fixed Now linux && !android && !gtk3 && !server.
menu_linux.go:42processMenu processed guard makes Menu.Update() a no-op (#discussion_r3251765580) 📋 Deferred — pre-existing bug, out of scope for the default-flip Filed #5464. Same bug exists in menu_linux_gtk3.go (inherited from #4958). Don't want to bundle a behavior fix into the mechanical-rename diff.
build-and-test-v3.yml:122 — apt package lists inverted (suppressed-low-confidence Copilot finding) ✅ Fixed Real bug — Copilot was right. The "GTK4 default" step was still installing GTK3 dev packages; "GTK3 legacy" had GTK4 packages. The labels were correctly flipped in my original commit but the package lists weren't swapped. Swapped now.
build-and-test-v3.yml:239 — same inversion in templates job (suppressed-low-confidence Copilot finding) ✅ Fixed Same swap applied. Both ubuntu-latest jobs run both install steps regardless (cache-apt-pkgs is idempotent), so the actual CI behavior was just unintentionally installing both stacks via misleading labels — but the labels now reflect what each step does.

Re-verification on lin-node1 (Ubuntu 26.04, both stacks installed)

Build Exit
go build ./... (default GTK4) 0 ✅
go build -tags gtk3 ./... (legacy) 0 ✅
go build -tags server ./... (server, post-fix — should exclude all GTK) 0 ✅ — empty output, no GTK code compiled

The -tags server build is the new verification: it was the gate Copilot was protecting against. Pre-de9b677, -tags server would have tried to compile GTK4 cgo code on Linux; now it cleanly excludes it, matching the legacy-GTK3 file's behavior.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

🧹 Nitpick comments (1)
v3/pkg/application/application_linux.go (1)

308-324: 💤 Low value

Unnecessary blank identifier assignments.

The packages dbus, filepath, and operatingsystem are 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

📥 Commits

Reviewing files that changed from the base of the PR and between 816a299 and de9b677.

📒 Files selected for processing (77)
  • .github/workflows/build-and-test-v3.yml
  • .github/workflows/build-cross-image.yml
  • .github/workflows/cross-compile-test-v3.yml
  • AGENTS.md
  • IMPLEMENTATION.md
  • docs/src/content/docs/contributing/getting-started.mdx
  • docs/src/content/docs/contributing/setup.mdx
  • docs/src/content/docs/getting-started/installation.mdx
  • docs/src/content/docs/guides/build/building.mdx
  • docs/src/content/docs/guides/build/linux.mdx
  • docs/src/content/docs/guides/cli.mdx
  • docs/src/content/docs/quick-start/installation.mdx
  • docs/src/content/docs/reference/dialogs.mdx
  • docs/src/content/docs/reference/window.mdx
  • v3/Taskfile.yaml
  • v3/examples/android/build/linux/nfpm/nfpm.yaml
  • v3/examples/badge-custom/build/linux/nfpm/nfpm.yaml
  • v3/examples/badge/build/linux/nfpm/nfpm.yaml
  • v3/examples/custom-protocol-example/build/linux/nfpm/nfpm.yaml
  • v3/examples/dock/build/linux/nfpm/nfpm.yaml
  • v3/examples/ios/build/linux/nfpm/nfpm.yaml
  • v3/examples/notifications/build/linux/nfpm/nfpm.yaml
  • v3/examples/webview-api-check/README.md
  • v3/internal/assetserver/webview/request_linux.go
  • v3/internal/assetserver/webview/request_linux_gtk3.go
  • v3/internal/assetserver/webview/responsewriter_linux.go
  • v3/internal/assetserver/webview/responsewriter_linux_gtk3.go
  • v3/internal/assetserver/webview/webkit_linux.go
  • v3/internal/assetserver/webview/webkit_linux_gtk3.go
  • v3/internal/capabilities/capabilities_linux.go
  • v3/internal/capabilities/capabilities_linux_gtk3.go
  • v3/internal/commands/updatable_build_assets/linux/nfpm/nfpm.yaml.tmpl
  • v3/internal/doctor/packagemanager/apt.go
  • v3/internal/doctor/packagemanager/dnf.go
  • v3/internal/doctor/packagemanager/emerge.go
  • v3/internal/doctor/packagemanager/eopkg.go
  • v3/internal/doctor/packagemanager/nixpkgs.go
  • v3/internal/doctor/packagemanager/pacman.go
  • v3/internal/doctor/packagemanager/zypper.go
  • v3/internal/operatingsystem/webkit_linux.go
  • v3/internal/operatingsystem/webkit_linux_gtk3.go
  • v3/pkg/application/application_linux.go
  • v3/pkg/application/application_linux_gtk3.go
  • v3/pkg/application/application_linux_gtk4.go
  • v3/pkg/application/gtkdispatch_linux.go
  • v3/pkg/application/gtkdispatch_linux_gtk3.go
  • v3/pkg/application/gtkdispatch_linux_gtk4.go
  • v3/pkg/application/linux_cgo.c
  • v3/pkg/application/linux_cgo.go
  • v3/pkg/application/linux_cgo.h
  • v3/pkg/application/linux_cgo_gtk3.go
  • v3/pkg/application/linux_cgo_gtk4.go
  • v3/pkg/application/menu_linux.go
  • v3/pkg/application/menu_linux_gtk3.go
  • v3/pkg/application/menu_linux_gtk4.go
  • v3/pkg/application/menuitem_linux.go
  • v3/pkg/application/menuitem_linux_gtk3.go
  • v3/test/manual/dialog/bin/file-directory-gtk4
  • v3/test/manual/dialog/bin/file-directory-gtk4-debug
  • v3/test/manual/dialog/bin/file-directory-gtk4-race
  • v3/test/manual/dialog/bin/file-open-gtk4
  • v3/test/manual/dialog/bin/file-open-gtk4-race
  • v3/test/manual/dialog/bin/file-open-multi-gtk4
  • v3/test/manual/dialog/bin/file-open-multi-gtk4-race
  • v3/test/manual/dialog/bin/file-save-gtk4
  • v3/test/manual/dialog/bin/file-save-gtk4-race
  • v3/test/manual/dialog/bin/message-error-gtk4
  • v3/test/manual/dialog/bin/message-error-gtk4-race
  • v3/test/manual/dialog/bin/message-info-gtk4
  • v3/test/manual/dialog/bin/message-info-gtk4-race
  • v3/test/manual/dialog/bin/message-question-gtk4
  • v3/test/manual/dialog/bin/message-question-gtk4-race
  • v3/test/manual/dialog/bin/message-warning-gtk4
  • v3/test/manual/dialog/bin/message-warning-gtk4-race
  • v3/tests/gtk4-benchmark/README.md
  • v3/tests/gtk4-benchmark/version_gtk3.go
  • v3/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

Comment thread IMPLEMENTATION.md
Comment thread v3/examples/badge-custom/build/linux/nfpm/nfpm.yaml Outdated
Comment thread v3/examples/badge/build/linux/nfpm/nfpm.yaml Outdated
Comment thread v3/examples/custom-protocol-example/build/linux/nfpm/nfpm.yaml Outdated
Comment thread v3/examples/notifications/build/linux/nfpm/nfpm.yaml Outdated
Comment on lines +697 to +701
func clipboardGet() string {
clip := C.gtk_clipboard_get(C.GDK_SELECTION_CLIPBOARD)
text := C.gtk_clipboard_wait_for_text(clip)
return C.GoString(text)
}

@coderabbitai coderabbitai Bot May 16, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.

Suggested change
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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pre-existing — clipboardGet leaking gchar* from gtk_clipboard_wait_for_text inherited from pre-flip linux_cgo.go. Tracked in #5465 as finding 4.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Comment on lines +1095 to +1108
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))
})
}

@coderabbitai coderabbitai Bot May 16, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pre-existing — execJS leaking C.CString("") inherited from pre-flip linux_cgo.go. Tracked in #5465 as finding 7.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes — please resolve. Tracked in #5465 (finding 7) and no action expected on #5463 itself.

Comment on lines +1838 to +1841
func (w *linuxWebviewWindow) zoomOut() {
ZoomInFactor := -1.10
w.setZoom(w.getZoom() * ZoomInFactor)
}

@coderabbitai coderabbitai Bot May 16, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

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.

Suggested change
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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Comment on lines +79 to 85
func (l linuxMenuItem) setHidden(hidden bool) {
InvokeSync(func() {
menuItemSetHidden(l, hidden)
l.blockSignal()
defer l.unBlockSignal()
widgetSetVisible(l.native, hidden)
})
l.isHidden = hidden
}

@coderabbitai coderabbitai Bot May 16, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

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.

Suggested change
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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Comment thread v3/pkg/application/menuitem_linux_gtk3.go
- 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.
@leaanthony

Copy link
Copy Markdown
Member Author

CodeRabbit round — all 14 actionable + 1 nitpick addressed. Pushed 1629542.

Fixed in 1629542 (5 comments)

Comment File Fix
🧹 Nitpick application_linux.go:308-324 Removed 3 redundant var _ = ... assignments — dbus, filepath, operatingsystem are all actually used in this file by isDarkMode / listenForSystemThemeChanges / getIconForFile / init
#3251816583 IMPLEMENTATION.md:7-10 Updated Decision 1.1's Build Tags block to show both default + legacy constraints with && !server (consistent with de9b677) and a sentence on server-mode exclusion
#3251816586 / #3251816592 / #3251816593 / #3251816595 badge / badge-custom / custom-protocol / notifications nfpm.yaml Restructured to match the android/dock/ios example pattern: Debian-correct top-level deps (libgtk-4-1, libwebkitgtk-6.0-4) + per-format overrides for rpm (gtk4, webkitgtk6.0) and archlinux (gtk4, webkitgtk-6.0). My original flip script naively swapped gtk3gtk4 at top-level for these 4 files; should have applied the overrides pattern instead.

Deferred to #5465 (9 comments — all pre-existing in master)

All 9 are bugs in the _gtk3.go legacy files that were inherited from the pre-flip _linux.go files. CodeRabbit's diff window saw them because of the rename, but git blame against master shows they predate #5463. Filed as #5465 with severity ranking:

Severity File:line Bug
🔴 high linux_cgo_gtk3.go:573 appName frees GLib-owned memory (heap corruption risk)
🟠 user-visible linux_cgo_gtk3.go:1841 zoomOut uses negative multiplier, clamps to 1.0
🟠 user-visible menuitem_linux_gtk3.go:85 setHidden inverted — SetHidden(true) makes item visible
🟡 memory leak linux_cgo_gtk3.go:701 clipboardGet leaks gchar*
🟡 memory leak linux_cgo_gtk3.go:1108 execJS leaks C.CString("")
🟡 correctness application_linux_gtk3.go:168 Early return skips startup handlers after ApplicationOpenedWithFile
🟡 correctness application_linux_gtk3.go:260 getTheme out-of-bounds + missing type-assert safety
🟡 correctness linux_cgo_gtk3.go:472 Calloc.String/Calloc.Free value receivers — appends discarded
🟢 noise menuitem_linux_gtk3.go:99 setAccelerator has dev fmt.Println

All affect the legacy -tags gtk3 path only. Default GTK4 path is unaffected. Bundling these into #5463 would have made the mechanical-rename diff much harder to review.

Re-verification on lin-node1 (Ubuntu 26.04)

Build Exit
go build ./pkg/application/ (default GTK4) 0 ✅
go build -tags gtk3 ./pkg/application/ (legacy) 0 ✅
go build -tags server ./pkg/application/ (server) 0 ✅

The blank-identifier removal in application_linux.go doesn't break the build — dbus / filepath / operatingsystem are used by real code in the same file.

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.
@leaanthony leaanthony merged commit 1c2ec6a into master May 16, 2026
88 of 89 checks passed
@leaanthony leaanthony deleted the feature/gtk4-default-flip branch May 16, 2026 07:38
leaanthony added a commit that referenced this pull request May 17, 2026
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
leaanthony added a commit that referenced this pull request May 17, 2026
)

* 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).
leaanthony added a commit that referenced this pull request May 18, 2026
#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.
leaanthony added a commit that referenced this pull request Jun 10, 2026
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[v3] Flip GTK4 + WebKitGTK 6.0 to default on Linux for v3.0.0 GA

2 participants