Skip to content

Native Menu Bars for Windows and MacOS #13752

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 22 commits into
base: main
Choose a base branch
from

Conversation

playmer
Copy link
Contributor

@playmer playmer commented Aug 15, 2025

Native Menu Bars get requested on a roughly monthly cadence in the Discord, and I've needed them in an SDL1 project I occasionally work on, that I'm foolishly optimistic I might be able to convince the maintainers to upgrade from one day.

So I decided to try to come up with something that was relatively capable between Win32 and Cocoa. It's still a bit rough as I didn't want to do a full documentation and correctness pass without some guidance on patterns I should consider switching to or concerns about the actual API we're surfacing. And I'll certainly need someone who is actually familiar with Objective-C to take a look over that, because I really don't know what I'm doing with marshalling between C and Objective-C there, to the extent that there's a warning failing the CI that I have no idea how to fix correctly:

/Users/runner/work/SDL-1/SDL-1/src/video/cocoa/SDL_cocoavideo.m:389:48: error: assigning to 'void *' from 'CFTypeRef _Nullable' (aka 'const void *') discards qualifiers [-Werror,-Wincompatible-pointer-types-discards-qualifiers]
menu_bar->common.item_common.platform_data = CFBridgingRetain(platform_menu);

There's an example that kicks the tires and seems to work as I'd expect, I'm sure I'm missing some permutations of APIs to try though.

Description

The API

I started with the Win32 API as I'm most familiar with it, and went from there. I slowly iterated up to the point where you could insert at positions after starting the Cocoa implementation and seeing it was well supported there as well. The general idea is to expose a simplification over the APIs here, and give you the basics. These were my needs when I was experimenting with menu-bars in Qt in the aforementioned SDL1 project.

Generally speaking, if the user just needs buttons they can do a one time setup of their MenuBar, and just listen for events that hand them the user driven event ids they passed in on creation of each menu item. Checkboxes come in the same way, and we let the user handle manually checking/unchecking, and disabling/enabling those same items, so they'd want to keep around the pointers to them.

Users will only need to keep around a reference to their MenuBar and if they call SDL_DestroyMenuItem on it, it'll be recursively destroyed. If they want to later remove or modify menus/items they'll want to keep those references around.

I'm sure the enums need a namespaced rename here, but I didn't want to try to figure it out yet, suggestions very much appreciated!

Abstract Implementation

I don't super love my design here, but I don't know what patterns are preferred and what we have access to internally to make some of them simpler, so I've ended up with essentially a tree of lists. I used something similar to SDL_Event to differentiate between the different nodes, and their common data, as they almost all need the same things.

The list format does lead to needing to choose to do some simple O(n) algorithms when a node needs its index on Windows. That could be mitigated by keeping the index in the Win32 platform data and recalculating it when things are added/removed, but I wanted to keep it simple for now in case I needed to completely rewrite this aspect of it.

Open Questions

One MenuBar Per Window?

I've not fully hammered out what destruction looks like here, although the basics are there and the example demonstrates. Related to this is what to do if the user tries to make multiple menu bars, where we should be keeping reference to the bars so we can destroy them when SDL_Quit is called.

Should we have inspection APIs for finding child items? Should we be storing their names for lookup?

I wasn't sure how we'd want to expose this in case folks threw away their references and wanted to go find them again later.

Checkables and Buttons?

I mostly separated these because I assumed they'd be different actual types of item on different platforms, but at least so far they're just both buttons and checkables on both platforms. I'm keeping the separation for now out of an abundance of caution.

Buttons on the MenuBar, MacOS, and the Application Menu

This is something that I really want, but it's unsupported on MacOS as far as I can tell. Right now I place buttons like this into the Application Menu, ignoring the given index. but I'm not particularly satisfied with any of it. We probably need a way to get the Application Menu as an SDL_MENU, so that things can be added directly, and maybe we just disallow buttons on the bar on MacOS, or entirely, I'm not sure.

Linux

Basically I'm not sure where to start here or how to know what's supported there, although I've spoken to my local Portals expert and he mentioned serializing a menubar representation into the GIO format and then maybe something could be developed from there for portals. Slouken has mentioned that some folks might be able to do it in Gtk, but it certainly needs some eyes on it either way.

*WithProperties?

I assume we'd want this, I just wanted to get the initial API considerations out there, and I figured I could add that towards the end once we're satisfied with it.

Context Menus?

As I was working on this and looking through the documentation, it seems like these APIs are closely associated with the Context Menus on both MacOS and Windows. I think with some API tweaks/an added function or two we could get native context menus for "free" as well, but I've not followed the lead yet. We'd probably want to decide before we lock this API in though.

Existing Issue(s)

#9590

Wasn't sure if I should put this in draft or not, as I know it needs some work, but it does need feedback. And if this isn't up to snuff, and it needs a complete redo, I fully understand, no worries.

@slouken slouken added this to the 3.4.0 milestone Aug 15, 2025
@slouken
Copy link
Collaborator

slouken commented Aug 15, 2025

I'm throwing this in the 3.4 milestone for feedback, but it might bump out a bit, since there isn't a Linux implementation yet.

@eafton
Copy link
Contributor

eafton commented Aug 15, 2025

@slouken Wouldnt it be easier to draw and handle the menus ourselves atleast on X11?

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.

3 participants