private void setTrayIcon(Stage primaryStage)
      throws ClassNotFoundException, UnsupportedLookAndFeelException, InstantiationException,
          IllegalAccessException {

    if (!SystemTray.isSupported()) {
      return;
    }

    SystemTray sTray = SystemTray.getSystemTray();
    primaryStage.setOnCloseRequest(arg0 -> primaryStage.hide());
    JPopupMenu popup = buildSystemTrayJPopupMenu(primaryStage);
    URL url = System.class.getResource("/logo-invert_small.png");
    Image img = Toolkit.getDefaultToolkit().getImage(url);
    TrayIcon icon = new TrayIcon(img, "Qabel");

    icon.setImageAutoSize(true);
    trayIconListener(popup, icon);

    try {
      sTray.add(icon);
    } catch (AWTException e) {
      logger.error("failed to add tray icon: " + e.getMessage(), e);
    }
  }
  private void trayIconListener(final JPopupMenu popup, TrayIcon icon) {

    Timer notificationTimer = new Timer();
    notificationTimer.schedule(
        new TimerTask() {
          @Override
          public void run() {
            if (visible && !inBound) {
              visible = !visible;
              popup.setVisible(visible);
            }
            inBound = false;
          }
        },
        250,
        1500);

    icon.addMouseMotionListener(
        new MouseMotionAdapter() {
          @Override
          public void mouseMoved(MouseEvent e) {
            inBound = true;
          }
        });

    popup.addMouseMotionListener(
        new MouseMotionAdapter() {
          @Override
          public void mouseMoved(MouseEvent e) {
            inBound = true;
          }
        });

    icon.addMouseListener(
        new MouseAdapter() {

          @Override
          public void mouseReleased(MouseEvent e) {

            if (e.getButton() != MouseEvent.BUTTON1) {
              return;
            }

            Point point = e.getPoint();
            Rectangle bounds = getScreenViewableBounds(getGraphicsDeviceAt(point));
            int x = point.x;
            int y = point.y;
            if (y < bounds.y) {
              y = bounds.y;
            } else if (y > bounds.y + bounds.height) {
              y = bounds.y + bounds.height;
            }
            if (x < bounds.x) {
              x = bounds.x;
            } else if (x > bounds.x + bounds.width) {
              x = bounds.x + bounds.width;
            }

            if (x + popup.getWidth() > bounds.x + bounds.width) {
              x = (bounds.x + bounds.width) - popup.getWidth();
            }
            if (y + popup.getWidth() > bounds.y + bounds.height) {
              y = (bounds.y + bounds.height) - popup.getHeight();
            }

            visible = !visible;

            if (visible) {
              popup.setLocation(x, y);
            }
            popup.setVisible(visible);
          }

          @Override
          public void mouseExited(MouseEvent e) {
            visible = false;
            popup.setVisible(visible);
          }
        });

    popup.addMouseListener(
        new MouseAdapter() {
          @Override
          public void mouseExited(MouseEvent e) {
            if ((e.getX() < popup.getBounds().getMaxX())
                && (e.getX() >= popup.getBounds().getMinX())
                && (e.getY() < popup.getBounds().getMaxY())
                && (e.getY() >= popup.getBounds().getMinY())) {
              return;
            }
            visible = false;
            popup.setVisible(visible);
          }
        });
  }