Skip to content

Fix GTK4 Linux menu updates#5539

Open
puneetdixit200 wants to merge 1 commit into
wailsapp:masterfrom
puneetdixit200:fix-linux-menu-update
Open

Fix GTK4 Linux menu updates#5539
puneetdixit200 wants to merge 1 commit into
wailsapp:masterfrom
puneetdixit200:fix-linux-menu-update

Conversation

@puneetdixit200

@puneetdixit200 puneetdixit200 commented Jun 4, 2026

Copy link
Copy Markdown

Fixes #5464

Summary

  • Rebuild GTK4 Linux menus on repeated Menu.Update() calls instead of returning early after the first process pass
  • Add a GTK4 menuClear helper and reset menu item indexes before rebuilding
  • Add a regression test and v3 changelog entry

Tests

  • go test ./pkg/application -run TestLinuxGTK4MenuUpdateRebuildsProcessedMenus
  • go test ./pkg/application

Note: coderabbit --plain was not run because the command is not installed locally.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed GTK4 Linux menu updating behavior. Previously, calling Menu.Update() on a menu that had been rendered would be ignored entirely. Menus are now properly cleared and rebuilt during updates, ensuring that menu modifications take effect correctly even when updating menus that have been previously displayed.

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

This PR fixes GTK4 Linux menus becoming a no-op after the first Menu.Update() call by implementing a menu-clearing mechanism that allows menus to be rebuilt rather than skipped on subsequent updates.

Changes

GTK4 Linux Menu Rebuild Fix

Layer / File(s) Summary
C-level menu clearing API
v3/pkg/application/linux_cgo.h, v3/pkg/application/linux_cgo.c
Header declares menu_clear(GMenu *menu), and C implementation removes all items from a menu by iterating in reverse from the last item to index 0 and calling g_menu_remove for each.
Go wrapper for menu clearing
v3/pkg/application/linux_cgo.go
New menuClear(menu *Menu) validates the Menu and native handle, calls C.menu_clear, and resets the menuItemCounters entry under lock.
Menu rebuild logic
v3/pkg/application/menu_linux.go
Changes linuxMenu.processMenu to clear the native menu and continue rebuilding when already processed, instead of early-returning; moves impl.processed = true to first-time initialization only.
Regression test
v3/pkg/application/linux_menu_regression_test.go
Test TestLinuxGTK4MenuUpdateRebuildsProcessedMenus verifies that processMenu does not early-return and calls menuClear before rebuild; includes functionBody helper to extract and inspect function implementations from source files.
Changelog entry
v3/UNRELEASED_CHANGELOG.md
Documents the GTK4 Linux menu rebuild fix under Fixed section.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • wailsapp/wails#4875: Introduces a menuClear/menu_clear helper and updates menu rebuilding logic to clear existing GTK menu contents before rebuilding on subsequent menu updates.

Suggested labels

Bug, Linux, v3, go

Suggested reviewers

  • leaanthony
  • atterpac

Poem

🐰 A menu that cleared and rebuilt,

No longer stuck in a processed guilt—

Now Updates dance, no more one-way guards,

Fresh items bloom in GTK's cards! 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix GTK4 Linux menu updates' clearly and concisely summarizes the main change: fixing a bug where GTK4 Linux menu updates became no-ops after the first call.
Description check ✅ Passed The PR description includes issue reference (#5464), a clear summary of changes, specific test commands, and addresses the checklist requirements, though some optional checklist items are not explicitly marked.
Linked Issues check ✅ Passed The PR fully implements the suggested fix from issue #5464: clearing/destroying the native menu and rebuilding on every Update() call, adding the menuClear helper, resetting menu indexes, and including regression tests.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing issue #5464: menu helper functions (C and Go), menu processing logic, changelog entry, and regression tests—no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"

🔧 Infer (1.2.0)
v3/pkg/application/linux_cgo.c

In file included from v3/pkg/application/linux_cgo.c:3:
v3/pkg/application/linux_cgo.h:6:10: fatal error: 'gtk/gtk.h' file not found
6 | #include <gtk/gtk.h>
| ^~~~~~~~~~~
1 error generated.
Error: the following clang command did not run successfully:
/opt/infer-linux-x86_64-v1.2.0/lib/infer/facebook-clang-plugins/clang/install/bin/clang-18
@/tmp/coderabbit-infer/9b4fb57a174735e48997944933d5fdf2e8d44a81-404c81ed9c8d9c90/tmp/clang_command_.tmp.35182c.txt
++Contents of '/tmp/coderabbit-infer/9b4fb57a174735e48997944933d5fdf2e8d44a81-404c81ed9c8d9c90/tmp/clang_command_.tmp.35182c.txt':
"-cc1" "-load"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../../facebook-clang-plugins/libtooling/build/FacebookClangPlugin.dylib"
"-add-plugin" "BiniouASTExporter" "-plugin-arg-BiniouASTExporter" "-"
"-plugin-arg-BiniouASTExporter" "PREPEND_CURRENT_DIR=1"
"-plugin-arg-BiniouASTExporter" "MAX_STRING_SIZE=65535" "-cc1" "-triple"
"x86_64-unknown-lin

... [truncated 759 characters] ...

inux-x86_64-v1.2.0/lib/infer/facebook-clang-plugins/clang/install/lib/clang/18/include"
"-internal-isystem" "/usr/local/include" "-internal-isystem"
"/usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include"
"-internal-externc-isystem" "/usr/include/x86_64-linux-gnu"
"-internal-externc-isystem" "/include" "-internal-externc-isystem"
"/usr/include" "-Wno-ignored-optimization-argument" "-Wno-everything"
"-ferror-limit" "19" "-fgnuc-version=4.2.1" "-fskip-odr-check-in-gmf"
"-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o"
"/tmp/coderabbit-infer/404c81ed9c8d9c90/file.o" "-x" "c"
"v3/pkg/application/linux_cgo.c" "-O0" "-fno-builtin" "-include"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../lib/clang_wrappers/global_defines.h"
"-Wno-everything"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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

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

17-17: 💤 Low value

The co-occurrence check correctly detects the regression pattern.

The logic checks for both "if impl.processed" and "return" anywhere in the function body. While this could theoretically cause false positives if unrelated return statements are added later, it accurately targets the specific bug pattern (early-return guard) that this PR fixes.

If the test becomes brittle in the future, consider refining the check to look for the specific pattern "if impl.processed" followed closely by "return" (e.g., within the same conditional block), or migrate to AST-based testing using go/parser and go/ast to structurally verify control flow rather than substring matching. However, the current approach is acceptable for a focused regression test.

🤖 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_menu_regression_test.go` at line 17, The current
test checks for co-occurrence using if strings.Contains(body, "if
impl.processed") && strings.Contains(body, "return"), which can yield false
positives; update the test to more precisely detect an early-return guard by
matching the pattern of "if impl.processed" followed closely by "return" (e.g.,
use a regex that allows only whitespace/comments/newlines between the if
condition and the return, or scan the subsequent N lines after finding "if
impl.processed" to assert a nearby "return"), or replace the substring approach
with an AST-based check using go/parser/go/ast to verify a conditional statement
whose body contains a return; operate on the same variable body (or parsed AST
root) and keep the assertion semantics but tighten the matching to avoid
unrelated return statements triggering the regression test.
🤖 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.

Nitpick comments:
In `@v3/pkg/application/linux_menu_regression_test.go`:
- Line 17: The current test checks for co-occurrence using if
strings.Contains(body, "if impl.processed") && strings.Contains(body, "return"),
which can yield false positives; update the test to more precisely detect an
early-return guard by matching the pattern of "if impl.processed" followed
closely by "return" (e.g., use a regex that allows only
whitespace/comments/newlines between the if condition and the return, or scan
the subsequent N lines after finding "if impl.processed" to assert a nearby
"return"), or replace the substring approach with an AST-based check using
go/parser/go/ast to verify a conditional statement whose body contains a return;
operate on the same variable body (or parsed AST root) and keep the assertion
semantics but tighten the matching to avoid unrelated return statements
triggering the regression test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f0627931-d2aa-429c-bfbc-941c387a47c2

📥 Commits

Reviewing files that changed from the base of the PR and between e4a3f36 and 9b4fb57.

📒 Files selected for processing (6)
  • v3/UNRELEASED_CHANGELOG.md
  • v3/pkg/application/linux_cgo.c
  • v3/pkg/application/linux_cgo.go
  • v3/pkg/application/linux_cgo.h
  • v3/pkg/application/linux_menu_regression_test.go
  • v3/pkg/application/menu_linux.go

@leaanthony

Copy link
Copy Markdown
Member

Thanks for this. I'm not sure of the value of the test as it just tests that the source code exists?

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] Menu.Update() is a no-op after first call due to processed guard in processMenu (Linux)

2 participants