Skip to content
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

Add notification tray icon on windows (boss key) #6341

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

adryzz
Copy link
Contributor

@adryzz adryzz commented Jul 20, 2024

This PR adds support for creating/removing notification tray icons, needed for boss key support.

This implementation is windows-only, i have a linux one half working but it'll be its own separate patch.

On windows, notification tray icons are closely intertwined with windowing logic, so i had to add 2 methods to IWindow to handle that.

osu!-side PR: ppy/osu#28972

out1.mp4

In my testing there's a problem with hiding the game window, and it looks like there's 2 windows, one that gets hidden and the other that remains, but i don't know if that's a framework issue or an osu! side issue.

out.mp4

EDIT: this only happens in fullscreen, borderless and windowed work just fine.

image

@Susko3
Copy link
Member

Susko3 commented Dec 25, 2024

SDL recently added tray icon support for windows, unix and macos. Documentation here: https://wiki.libsdl.org/SDL3/CategoryTray.

Using this API gets us the other two platforms for free.

@adryzz
Copy link
Contributor Author

adryzz commented Dec 27, 2024

that's awesome, i'll start using it then

@adryzz
Copy link
Contributor Author

adryzz commented Dec 27, 2024

fixed conflicts, will now switch to the SDL3 API

@Susko3
Copy link
Member

Susko3 commented Dec 31, 2024

I think the API should be declarative, and make use of the SDL tray menu nesting.

public interface IDesktopWindow : IWindow
{
    // dispose to remove the tray icon
    IDisposable CreateTrayIcon(TrayIcon icon);
}


static void Main()
{
    IWindow window;
    if (window is IDesktopWindow desktopWindow)
    {
        var icon = new TrayIcon
        {
            Label = "osu!",
            Icon = imageSharpImage,
            Menu = new TrayMenuEntry[]
            {
                new TrayButton
                {
                    Label = "Open osu!",
                    Default = true, // label should be in bold and double-clicking the icon will invoke this action
                    Action = () => openOsuAndDisposeTray(),
                },
                new TraySubmenu
                {
                    Label = "Example submenu",
                    Entries = new TrayMenuEntry[]
                    {
                        new TrayCheckbox
                        {
                            Checked = true,
                            Action = b => Logger.Log(b ? "checked" : "unchecked"),
                        }
                    }
                },
                new TraySeparator(),
                new TrayButton
                {
                    Label = "Exit",
                    Action = () => closeTheGameAndDisposeTray(),
                }
            }
        }

        var activeTrayIcon = desktopWindow.CreateTrayIcon(icon)
    }
}

Example tray from above definition

We just walk the tree and call the appropriate SDL functions in order. The created tray icon and menu are readonly, a game can delete the old menu and create a new one if updates are needed.

I might take a stab at it next year.

@adryzz
Copy link
Contributor Author

adryzz commented Dec 31, 2024

yes, actually it's exactly the design i first had in mind when i started working on this many months ago.

when i get home tomorrow i'll get it all working and up to snuff

@adryzz
Copy link
Contributor Author

adryzz commented Jan 2, 2025

alright got it to mostly work in a local branch, but the new version of ppy.SDL3-CS isn't released yet so it only works with a local nuget package

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants