I am trying to make a xlib traybar for X11 where it embeds the tray icons using XEMBED as described in the tray specs. However when I close the application with the tray icon it just removes it from the container window but the black container window rectangle and the entry in my code still exists.
In the XEMBED documentation it says
It is the responsibility of the embedder to keep track of all forwarded accelerators and to remove them when the client window dies.
However my application does not get any events or indication when a embedded window dies.
I basically only receive a dock request event and nothing else afterwards. When a dock request event comes in I create a child window for my panel which contains the tray window and reparent it like this:
enum trayIconSize = 24; // dimensions of icon
icon.trayWindow = XCreateWindow(x.display, panel.window, 0, 0, ...);
icon.ownerHandle = event.data.l[2]; // window id of icon which wants to dock
XReparentWindow(x.display, icon.ownerHandle, icon.trayWindow, 0, 0);
XMoveResizeWindow(x.display, icon.ownerHandle, 0, 0, trayIconSize, trayIconSize);
Adding it to the panel works without any problems but I don't know how to check when to remove it again.
How do I make my application receive close events for those tray icons or how do I check if the reparented window still exists?
I have actually done this before myself: https://github.com/adamdruppe/taskbar it has hacks for my specific setup in the width thing, but most of it should be reasonably usable and the code might help guide you.
But what you want to do is ask for events on the icon window. It has been a while, so I'm kinda using my own code as a guide here, but when I got the dock request, I called XSelectInput(dd, id, EventMask.StructureNotifyMask);
StructureNotifyMask
subscribes to events including MapNotify
, DestroyNotify
, you prolly see where this is going :)
Once you have selected the input on the icon window, you regular event loop can check for the DestroyNotify
and UnmapNotify
events (my code checks both, tbh, I'm not sure which one actually triggers when the icon is removed) and compare the .window
member of the event to your icon's window ID. If it matches, go ahead and remove it from your list because it is gone now.
My taskbar does seem to have a bug if the application crashes as opposed to being closed normally, so I might still be missing something, but checking the event works in most cases.