Skip to content

SDL_UnregisterTray unexpectedly triggers SDL_EVENT_QUIT event (Create/Destroy tray for feature detection) #13119

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
silbinarywolf opened this issue May 25, 2025 · 3 comments · May be fixed by #13124
Milestone

Comments

@silbinarywolf
Copy link

silbinarywolf commented May 25, 2025

SDL: 3.2.10

The problem

I have logic in my Zig application where I create a tray with SDL_CreateTray and then destroy it with SDL_DestroyTray on start-up to detect if the operating system supports the feature.

Calling SDL_DestroyTray has unexpected behaviour where it calls SDL_UnregisterTray which sends an SDL_EVENT_QUIT event because it detects that are no more windows active and it immediately closes the application on the first-frame.

if (toplevel_count == 0) {
SDL_SendQuit();
}

Workarounds for others that find this

  • If you want to do this check, create your application window first.
  • Temporarily disable the hint SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE
    if (!SDL_GetHintBoolean(SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE, true)) {
    return;
    }

Proposed solutions

  • A new function to detect if trays are supported. SDL_HasTraySupport or something.
  • Avoid triggering quit unless a window has at least been created once or only trigger if the event queue has been polled at least once.
@Semphriss
Copy link
Contributor

Sending SDL_EVENT_QUIT when closing the last active tray icon when there are no windows is the intended behavior with #11743. I can add a function to check for tray support, I'll look into that shortly.

What's your use case for checking if trays are supported before you'd need one? Generally speaking, you should check if trays are supported only when comes the time to create one you'll need, and either keep it if it works or run the fallback behavior if it doesn't. The reasons are that the situation may have changed (e. g. a Unix user may have installed AppIndicator in the meantime), and that some systems will temporarily show the dummy tray while it exists, which may be confusing for users.

@slouken slouken added this to the 3.4.0 milestone May 25, 2025
@Semphriss Semphriss linked a pull request May 25, 2025 that will close this issue
@silbinarywolf
Copy link
Author

My use-case for checking for tray support is that I want the user to be able to configure whether pressing X on my application will minimize to tray or not.

For Linux/other systems that don't support a tray, I'd rather not show this as an option at all so being able to detect if it can be done or not would be ideal.

Use cases

  • If system tray is supported, pressing X (close on the main app window) will create the tray and minimize to it.
  • In "Options" screen, if system tray is supported, the user can disable pressing X (close) minimizing the application

Example of feature in Discord
Image

@Semphriss
Copy link
Contributor

To my understanding of the various system docs, the expected workflow is to create a tray icon when the app starts and keep that one for the process' lifetime, and decide whether to show the related options based on whether the tray icon was created successfully.

I'm not sure if any app only creates a tray icon when the main window is first closed, but if you choose to do this for your app, I would recommend testing across systems to make sure the tray icons react as expected. On my system, the tray bar typically takes a second or two to refresh when an icon is created or removed, which may affect the user experience if tray icons come and go.

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 a pull request may close this issue.

3 participants