package com.ts3client.ui; import com.ts3client.ui.tray.AwtTray; import com.ts3client.ui.tray.TrayBackend; import com.ts3client.ui.tray.X11Tray; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.JWindow; import javax.swing.SwingUtilities; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import java.awt.Frame; import java.awt.Image; import java.awt.MenuItem; import java.awt.PopupMenu; import java.util.function.IntFunction; /** * The system tray icon. It shows the local client's state on the active server — * the same badge the tree draws next to a nickname, so it turns green while * speaking and into the muted microphone or speaker when muted — and brings the * window back to the front when clicked. * *
The icon is docked by {@link X11Tray} where the panel can show a transparent
* one, and by {@link AwtTray} everywhere else. On a desktop with no tray at all
* nothing is installed and every call here is a no-op.
*/
final class TrayController {
private final MainFrame frame;
private final Runnable onQuit;
private final TrayBackend tray;
/** What is on screen now, so repeated updates don't touch the tray. */
private SelfState state;
private String tooltip = "";
TrayController(MainFrame frame, Runnable onQuit) {
this.frame = frame;
this.onQuit = onQuit;
this.tray = install();
}
/** What happened when the icon was installed, for the diagnostics in the chat log. */
String status() {
return tray == null
? "System tray: no icon could be installed (run with -Dts3j.tray.debug=true for why)."
: "System tray: " + tray.description() + ".";
}
/** @return the backend that took the icon, or {@code null} when none could */
private TrayBackend install() {
TrayBackend.Listener listener = new TrayBackend.Listener() {
@Override
public void activated() {
SwingUtilities.invokeLater(TrayController.this::show);
}
@Override
public void menuRequested(int x, int y) {
SwingUtilities.invokeLater(() -> showMenu(x, y));
}
};
// -Dts3j.tray=awt|x11 pins the backend; by default the transparent one is
// tried first and AWT's picks up whatever it leaves.
String choice = System.getProperty("ts3j.tray", "auto");
IntFunction