Native menu items on WinForms are never deleted
- Dominant language
- Python
- Stars
- 5.4k
- Forks
- 827
- Avg merge
- 9h 45m
- Merged PRs (30d)
- 58
Description
### Describe the bug
Each time `Window._impl.create_menus()` is called on the WinForms backend it creates new copies of every native menu item. However the old objects are never removed from the `Window._impl.native` list.
### How to reproduce the bug
1. Run the minimal example.
2. The expectation would be to see ``Native instances of `cmd`: 1`` printed each time.
### Minimum example code
```shell
import toga
class MinimalApp(toga.App):
def __init__(self):
super().__init__(
formal_name="MinimalApp", app_id="com.example.minimal.app"
)
def startup(self):
self.main_window = toga.MainWindow(title=self.formal_name)
self.main_window.show()
def on_running(app=self):
all_commands = [cmd for cmd in app.commands._commands.values()]
cmd = all_commands[0]
group = cmd.group
for i in range(10):
new_cmd = toga.Command(text = f"Item {i}", group=group, action=None)
app.commands.add(new_cmd)
print(f"Native instances of `cmd`: {len(cmd._impl.native)}")
self.on_running = on_running
def main():
return MinimalApp()
if __name__ == "__main__":
app = main()
app.main_loop()
```
### Screenshots
_No response_
### Environment details
- Operating system and version: Windows 11
- Python version: 3.13
- Software versions:
- Toga: 0.5.5
### Logs
```
```
### Additional context
The issue is not present on the macOS backend since the `toga_cocoa.command.Command` class has a `remove_menu_item` method which is called. One solution could be to use such a method on the WinForms backend. Another could be to replace the `toga_winforms.command.Command.native` list with a `dict` of the form `{id(MainWindow): Command}`.
In either case, the native menu items should also be deleted whenever the MainWindow instance is deleted.
I think the issue is also present on toolbar items, and I haven't looked at other backends.
Contributor guide
Research direction
Start in the WinForms implementation at Window._impl.create_menus() and toga_winforms.command.Command, then compare the macOS Command.remove_menu_item behavior described in the issue. Confirm that repeated menu creation and MainWindow deletion release old native items; also check whether the same lifecycle issue affects toolbar items.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- desktop
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100