Skip to content

SNI/DBus tray support (take 2)#15189

Merged
slouken merged 7 commits intolibsdl-org:mainfrom
eafton:tray-dbus2
Apr 10, 2026
Merged

SNI/DBus tray support (take 2)#15189
slouken merged 7 commits intolibsdl-org:mainfrom
eafton:tray-dbus2

Conversation

@eafton
Copy link
Copy Markdown
Contributor

@eafton eafton commented Mar 10, 2026

The previous iteration of this had severe bugs on KDE and MATE...

@eafton eafton marked this pull request as draft March 10, 2026 19:18
@eafton
Copy link
Copy Markdown
Contributor Author

eafton commented Mar 10, 2026

@slouken What do you think?

@slouken
Copy link
Copy Markdown
Collaborator

slouken commented Mar 10, 2026

Looks promising!

@eafton
Copy link
Copy Markdown
Contributor Author

eafton commented Mar 16, 2026

@C0rn3j Once this is merged I will start working on the extra features you requested (scroll callbacks, textual icon descriptions, showing/hiding), do you have any more ideas?

@C0rn3j
Copy link
Copy Markdown

C0rn3j commented Mar 16, 2026

I don't, I think what I highlighted before was all there was for our use case with Tauon

@slouken
Copy link
Copy Markdown
Collaborator

slouken commented Mar 16, 2026

@eafton, can you summarize the benefits and risks of accepting this PR vs what we have currently?

@eafton
Copy link
Copy Markdown
Contributor Author

eafton commented Mar 16, 2026

@eafton, can you summarize the benefits and risks of accepting this PR vs what we have currently?

The current implementation uses a library declared obsolete (see https://github.com/AyatanaIndicators/libayatana-appindicator), and it uses GTK3 which causes all kinds of problems with synbol conflicts, state corruption errors, etc if the client application also wants to use GTK3 (or even anything GLib for that matter from my experience), the current implementation also does not support a few features like the icon click handlers and tooltips. And we can use icon surfaces directly without encoding them to PNG, saving them to disk, and messing with icon theme paths.

There are only two risks that come to mind with this implementation that come to mind:

  1. This does not support the old XEmbed based protocol, so desktops like TDE that only support the XEmbed protocol and dont support the SNI protocol will not have tray icons. I do have a plan for an XEmbed driver that I will discuss privately though.
  2. This code uses the NewMenu extension which some panels like Waybar and mate-panel do not support, It is supported by GNOME, KDE, etc though, and I created issues in MATE and Waybar for this.

@sulix
Copy link
Copy Markdown
Contributor

sulix commented Mar 17, 2026

FWIW: I'm very much in favour of this approach, but there are definitely still a lot of bugs in this implementation.

In particular, it has lots of invalid memory accesses if tray icons are destroyed and re-created. A quick addition of some code to reset various variables to NULL upon their destruction at least gets it to not crash here (see patch below), but there are still several others, and I suspect there are some more issues with thread safety I'm not encountering personally.

index fcb86331b..993b0a200 100644
--- a/src/tray/unix/SDL_dbustray.c
+++ b/src/tray/unix/SDL_dbustray.c
@@ -545,6 +545,7 @@ void DestroyMenu(SDL_TrayMenu *menu)
 
             if (entry->sub_menu) {
                 DestroyMenu((SDL_TrayMenu *)entry->sub_menu);
+                entry->sub_menu = NULL;
             }
             SDL_free(item);
             SDL_free(entry);
@@ -582,6 +583,7 @@ void DestroyTray(SDL_Tray *tray)
     /* Destroy the menus and entries */
     if (tray->menu) {
         DestroyMenu(tray->menu);
+        tray->menu = NULL;
     }
 
     /* Free the tray */
diff --git a/src/tray/unix/SDL_tray.c b/src/tray/unix/SDL_tray.c
index 6addef54b..c3eed64b9 100644
--- a/src/tray/unix/SDL_tray.c
+++ b/src/tray/unix/SDL_tray.c
@@ -346,5 +346,6 @@ void SDL_DestroyTray(SDL_Tray *tray)
 
     if (!SDL_GetActiveTrayCount()) {
         driver->DestroyDriver(driver);
+        driver = NULL;
     }
 }

@eafton
Copy link
Copy Markdown
Contributor Author

eafton commented Mar 17, 2026

FWIW: I'm very much in favour of this approach, but there are definitely still a lot of bugs in this implementation.

In particular, it has lots of invalid memory accesses if tray icons are destroyed and re-created. A quick addition of some code to reset various variables to NULL upon their destruction at least gets it to not crash here (see patch below), but there are still several others, and I suspect there are some more issues with thread safety I'm not encountering personally.

index fcb86331b..993b0a200 100644
--- a/src/tray/unix/SDL_dbustray.c
+++ b/src/tray/unix/SDL_dbustray.c
@@ -545,6 +545,7 @@ void DestroyMenu(SDL_TrayMenu *menu)
 
             if (entry->sub_menu) {
                 DestroyMenu((SDL_TrayMenu *)entry->sub_menu);
+                entry->sub_menu = NULL;
             }
             SDL_free(item);
             SDL_free(entry);
@@ -582,6 +583,7 @@ void DestroyTray(SDL_Tray *tray)
     /* Destroy the menus and entries */
     if (tray->menu) {
         DestroyMenu(tray->menu);
+        tray->menu = NULL;
     }
 
     /* Free the tray */
diff --git a/src/tray/unix/SDL_tray.c b/src/tray/unix/SDL_tray.c
index 6addef54b..c3eed64b9 100644
--- a/src/tray/unix/SDL_tray.c
+++ b/src/tray/unix/SDL_tray.c
@@ -346,5 +346,6 @@ void SDL_DestroyTray(SDL_Tray *tray)
 
     if (!SDL_GetActiveTrayCount()) {
         driver->DestroyDriver(driver);
+        driver = NULL;
     }
 }

Sorry for not catching these memory errors, I was on a wild goose chase of fixing compatability errors with desktops.

I am currenly away from my desk, If you have found more bugs please let me know so I can fix them when I get home.

As for thread safety, the tray subsystem is designed to be used on the main thread, I need to add the thread checks present on other tray implementations into CreateTray.

@eafton
Copy link
Copy Markdown
Contributor Author

eafton commented Mar 18, 2026

@sulix @slouken Mind having another look? Squashed my bugfix commits.

@sulix
Copy link
Copy Markdown
Contributor

sulix commented Mar 19, 2026

Much, much better. I'm only seeing one valgrind warning now, and there aren't any crashes even under the more extreme use case of repeatedly creating/destroying tray icons.

The valgrind warning seems to be an issue with dbus (maybe struct padding or something?) rather than SDL, but I've included it here in case you want to look into it further…

Valgrind: Syscall param sendmsg(msg.msg_iov[1]) points to uninitialised byte(s) (allocated dbus_message_iter_append_basic)
==3551033== Syscall param sendmsg(msg.msg_iov[1]) points to uninitialised byte(s)
==3551033==    at 0x530EE7C: sendmsg (sendmsg.c:28)
==3551033==    by 0x5BC2135: _dbus_write_socket_with_unix_fds_two.constprop.0 (dbus-sysdeps-unix.c:626)
==3551033==    by 0x5BBCD8E: do_writing (dbus-transport-socket.c:619)
==3551033==    by 0x5BBD167: socket_do_iteration (dbus-transport-socket.c:1131)
==3551033==    by 0x5BA13AE: _dbus_transport_do_iteration (dbus-transport.c:1013)
==3551033==    by 0x5BA13AE: _dbus_transport_do_iteration (dbus-transport.c:996)
==3551033==    by 0x5BA13AE: _dbus_connection_do_iteration_unlocked (dbus-connection.c:1229)
==3551033==    by 0x5BA147D: _dbus_connection_send_preallocated_unlocked_no_update (dbus-connection.c:2069)
==3551033==    by 0x5BA2A93: _dbus_connection_send_preallocated_and_unlock (dbus-connection.c:2089)
==3551033==    by 0x5BA2A93: _dbus_connection_send_and_unlock (dbus-connection.c:2126)
==3551033==    by 0x5BA2A93: dbus_connection_send (dbus-connection.c:3336)
==3551033==    by 0x4B72A06: SDL_DBus_UpdateMenu (SDL_dbus.c:1843)
==3551033==    by 0x4B651EC: RemoveTrayEntry (SDL_dbustray.c:938)
==3551033==  Address 0x1c3030f0 is 0 bytes inside a block of size 320 alloc'd
==3551033==    at 0x484FEEB: realloc (vg_replace_malloc.c:1804)
==3551033==    by 0x5BBF0E6: reallocate_for_length (dbus-string.c:397)
==3551033==    by 0x5BBF0E6: set_length (dbus-string.c:438)
==3551033==    by 0x5BBFECD: open_gap.lto_priv.0 (dbus-string.c:459)
==3551033==    by 0x5BC0BCA: copy (dbus-string.c:1276)
==3551033==    by 0x5BC0BCA: _dbus_string_copy_len (dbus-string.c:1446)
==3551033==    by 0x5BC3171: marshal_len_followed_by_bytes.lto_priv.0 (dbus-marshal-basic.c:759)
==3551033==    by 0x5BABE8A: marshal_string (dbus-marshal-basic.c:791)
==3551033==    by 0x5BABE8A: _dbus_marshal_write_basic (dbus-marshal-basic.c:888)
==3551033==    by 0x5BABE8A: _dbus_type_writer_write_basic_no_typecode (dbus-marshal-recursive.c:1604)
==3551033==    by 0x5BABE8A: _dbus_type_writer_write_basic_no_typecode (dbus-marshal-recursive.c:1599)
==3551033==    by 0x5BABE8A: _dbus_type_writer_write_basic (dbus-marshal-recursive.c:2326)
==3551033==    by 0x5BB0390: dbus_message_iter_append_basic (dbus-message.c:2858)
==3551033==    by 0x4B6ED3D: MenuAppendItemProperties (SDL_dbus.c:961)
==3551033==    by 0x4B6F916: MenuHandleGetLayout (SDL_dbus.c:1110)
==3551033==    by 0x4B71990: MenuMessageHandler (SDL_dbus.c:1598)
==3551033==    by 0x5BA5383: _dbus_object_tree_dispatch_and_unlock (dbus-object-tree.c:1021)
==3551033==    by 0x5BA5383: dbus_connection_dispatch (dbus-connection.c:4758)
==3551033==    by 0x5BA5383: dbus_connection_dispatch (dbus-connection.c:4586)
==3551033==    by 0x4B6445D: UpdateTray (SDL_dbustray.c:610)

But this is definitely working well enough for me so far! Thanks very much!

@eafton
Copy link
Copy Markdown
Contributor Author

eafton commented Mar 19, 2026

Much, much better. I'm only seeing one valgrind warning now, and there aren't any crashes even under the more extreme use case of repeatedly creating/destroying tray icons.

The valgrind warning seems to be an issue with dbus (maybe struct padding or something?) rather than SDL, but I've included it here in case you want to look into it further…

Valgrind: Syscall param sendmsg(msg.msg_iov[1]) points to uninitialised byte(s) (allocated dbus_message_iter_append_basic)

==3551033== Syscall param sendmsg(msg.msg_iov[1]) points to uninitialised byte(s)
==3551033==    at 0x530EE7C: sendmsg (sendmsg.c:28)
==3551033==    by 0x5BC2135: _dbus_write_socket_with_unix_fds_two.constprop.0 (dbus-sysdeps-unix.c:626)
==3551033==    by 0x5BBCD8E: do_writing (dbus-transport-socket.c:619)
==3551033==    by 0x5BBD167: socket_do_iteration (dbus-transport-socket.c:1131)
==3551033==    by 0x5BA13AE: _dbus_transport_do_iteration (dbus-transport.c:1013)
==3551033==    by 0x5BA13AE: _dbus_transport_do_iteration (dbus-transport.c:996)
==3551033==    by 0x5BA13AE: _dbus_connection_do_iteration_unlocked (dbus-connection.c:1229)
==3551033==    by 0x5BA147D: _dbus_connection_send_preallocated_unlocked_no_update (dbus-connection.c:2069)
==3551033==    by 0x5BA2A93: _dbus_connection_send_preallocated_and_unlock (dbus-connection.c:2089)
==3551033==    by 0x5BA2A93: _dbus_connection_send_and_unlock (dbus-connection.c:2126)
==3551033==    by 0x5BA2A93: dbus_connection_send (dbus-connection.c:3336)
==3551033==    by 0x4B72A06: SDL_DBus_UpdateMenu (SDL_dbus.c:1843)
==3551033==    by 0x4B651EC: RemoveTrayEntry (SDL_dbustray.c:938)
==3551033==  Address 0x1c3030f0 is 0 bytes inside a block of size 320 alloc'd
==3551033==    at 0x484FEEB: realloc (vg_replace_malloc.c:1804)
==3551033==    by 0x5BBF0E6: reallocate_for_length (dbus-string.c:397)
==3551033==    by 0x5BBF0E6: set_length (dbus-string.c:438)
==3551033==    by 0x5BBFECD: open_gap.lto_priv.0 (dbus-string.c:459)
==3551033==    by 0x5BC0BCA: copy (dbus-string.c:1276)
==3551033==    by 0x5BC0BCA: _dbus_string_copy_len (dbus-string.c:1446)
==3551033==    by 0x5BC3171: marshal_len_followed_by_bytes.lto_priv.0 (dbus-marshal-basic.c:759)
==3551033==    by 0x5BABE8A: marshal_string (dbus-marshal-basic.c:791)
==3551033==    by 0x5BABE8A: _dbus_marshal_write_basic (dbus-marshal-basic.c:888)
==3551033==    by 0x5BABE8A: _dbus_type_writer_write_basic_no_typecode (dbus-marshal-recursive.c:1604)
==3551033==    by 0x5BABE8A: _dbus_type_writer_write_basic_no_typecode (dbus-marshal-recursive.c:1599)
==3551033==    by 0x5BABE8A: _dbus_type_writer_write_basic (dbus-marshal-recursive.c:2326)
==3551033==    by 0x5BB0390: dbus_message_iter_append_basic (dbus-message.c:2858)
==3551033==    by 0x4B6ED3D: MenuAppendItemProperties (SDL_dbus.c:961)
==3551033==    by 0x4B6F916: MenuHandleGetLayout (SDL_dbus.c:1110)
==3551033==    by 0x4B71990: MenuMessageHandler (SDL_dbus.c:1598)
==3551033==    by 0x5BA5383: _dbus_object_tree_dispatch_and_unlock (dbus-object-tree.c:1021)
==3551033==    by 0x5BA5383: dbus_connection_dispatch (dbus-connection.c:4758)
==3551033==    by 0x5BA5383: dbus_connection_dispatch (dbus-connection.c:4586)
==3551033==    by 0x4B6445D: UpdateTray (SDL_dbustray.c:610)

But this is definitely working well enough for me so far! Thanks very much!

I looked at the Valgrind log you have attached and it does seem to be a libdbus problem, thank you for reporting these issues though, I am also glad its working well now.

@slouken
Copy link
Copy Markdown
Collaborator

slouken commented Mar 22, 2026

In general this looks pretty good. I added a few comments above.

In addition, I see you have a tray driver construct in the unix tray handling. Do you anticipate there being other drivers added in the future?

@eafton
Copy link
Copy Markdown
Contributor Author

eafton commented Mar 22, 2026

In general this looks pretty good. I added a few comments above.

In addition, I see you have a tray driver construct in the unix tray handling. Do you anticipate there being other drivers added in the future?

Thanks, I shortened the credits and fixed the whitespace issues caused by clang-format.

I added the driver system due to 3 main reasons:

  1. FDO might have another go at standardizing the KDE SNI protocol, this allows us to handle the changes that could end up being made while still keeping support for the old KDE variant of the protocol.
  2. Someone could come up with a new protocol down the road, FOSS is unpredictable...
  3. So we can add XEmbed tray support for older desktops and distros if we decide to.

@eafton
Copy link
Copy Markdown
Contributor Author

eafton commented Mar 22, 2026

@ssokolow Sorry for "stealing" your idea, I just wanted to have a go at it myself after your efforts seemingly stalled...

@ssokolow
Copy link
Copy Markdown

Not at all a problem. I just had some spare time and some prior experience poking at the relevant APIs and wanted to share that knowledge.

I didn't anticipate having time to write and debug C instead of Python to begin with.

@eafton
Copy link
Copy Markdown
Contributor Author

eafton commented Apr 10, 2026

@icculus Mind looking at this again and #15246?

@slouken
Copy link
Copy Markdown
Collaborator

slouken commented Apr 10, 2026

@icculus, I'll go ahead and merge this. I don't have time to look at the other issue right now, but if you want to take a look and provide feedback, please do!

@slouken slouken merged commit 8c024f4 into libsdl-org:main Apr 10, 2026
45 checks passed
@C0rn3j
Copy link
Copy Markdown

C0rn3j commented Apr 10, 2026

I recommend enabling viewing of tabs vs spaces, some wonky indentation made it in.

I do mean in the code editor, but this is the GitHub Refined view:

image

@Kontrabant
Copy link
Copy Markdown
Contributor

I ran clang-format over the changes, which should fix the whitespace issues.

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.

6 participants