diff --git a/app/src/main/java/io/xpipe/app/core/AppMainWindow.java b/app/src/main/java/io/xpipe/app/core/AppMainWindow.java index de336718..d3b39b1c 100644 --- a/app/src/main/java/io/xpipe/app/core/AppMainWindow.java +++ b/app/src/main/java/io/xpipe/app/core/AppMainWindow.java @@ -50,6 +50,10 @@ public class AppMainWindow { return INSTANCE; } + public static AppMainWindow getInstance() { + return INSTANCE; + } + private synchronized void onChange() { lastUpdate = Instant.now(); if (thread == null) { diff --git a/app/src/main/java/io/xpipe/app/core/AppTray.java b/app/src/main/java/io/xpipe/app/core/AppTray.java index 87a8756d..4a9e9cfd 100644 --- a/app/src/main/java/io/xpipe/app/core/AppTray.java +++ b/app/src/main/java/io/xpipe/app/core/AppTray.java @@ -5,7 +5,9 @@ import io.xpipe.app.core.mode.OperationMode; import io.xpipe.app.issue.ErrorEvent; import io.xpipe.app.issue.ErrorHandler; import javafx.application.Platform; +import lombok.SneakyThrows; +import javax.swing.*; import java.awt.*; import java.time.Duration; import java.time.Instant; @@ -15,11 +17,13 @@ public class AppTray { private static AppTray INSTANCE; private final FXTrayIcon icon; private final ErrorHandler errorHandler; + private final TrayIcon privateTrayIcon; + @SneakyThrows private AppTray() { - var url = AppResources.getResourceURL(AppResources.XPIPE_MODULE, "img/logo/logo_48x48.png"); + var url = AppResources.getResourceURL(AppResources.XPIPE_MODULE, "img/logo/logo_48x48.png").orElseThrow(); - var builder = new FXTrayIcon.Builder(App.getApp().getStage(), url.orElse(null)) + var builder = new FXTrayIcon.Builder(App.getApp().getStage(), url) .menuItem(AppI18n.get("open"), e -> { OperationMode.switchToAsync(OperationMode.GUI); }); @@ -44,6 +48,11 @@ public class AppTray { .toolTip("XPipe") .build(); this.errorHandler = new TrayErrorHandler(); + + var tray = SystemTray.getSystemTray(); + var f = icon.getClass().getDeclaredField("trayIcon"); + f.setAccessible(true); + privateTrayIcon = (TrayIcon) f.get(this.icon); } public static void init() { @@ -56,17 +65,22 @@ public class AppTray { public void show() { icon.show(); + + // Remove functionality to show stage when primary clicked and replace it with our own + SwingUtilities.invokeLater(() -> { + privateTrayIcon.removeActionListener(privateTrayIcon.getActionListeners()[0]); + privateTrayIcon.addActionListener(e -> { + OperationMode.switchToAsync(OperationMode.GUI); + }); + }); } public void hide() { // Ugly fix to prevent platform exit in icon.hide() try { var tray = SystemTray.getSystemTray(); - var f = icon.getClass().getDeclaredField("trayIcon"); - f.setAccessible(true); - var ti = (TrayIcon) f.get(this.icon); EventQueue.invokeLater(() -> { - tray.remove(ti); + tray.remove(privateTrayIcon); }); } catch (Exception ex) { ErrorEvent.fromThrowable(ex).handle(); diff --git a/app/src/main/java/io/xpipe/app/core/mode/GuiMode.java b/app/src/main/java/io/xpipe/app/core/mode/GuiMode.java index 37d75e55..fcbb05cd 100644 --- a/app/src/main/java/io/xpipe/app/core/mode/GuiMode.java +++ b/app/src/main/java/io/xpipe/app/core/mode/GuiMode.java @@ -2,6 +2,7 @@ package io.xpipe.app.core.mode; import io.xpipe.app.core.App; import io.xpipe.app.core.AppGreetings; +import io.xpipe.app.core.AppMainWindow; import io.xpipe.app.issue.*; import io.xpipe.app.update.UpdateChangelogAlert; import io.xpipe.app.util.PlatformState; @@ -22,15 +23,20 @@ public class GuiMode extends PlatformMode { super.platformSetup(); CountDownLatch latch = new CountDownLatch(1); Platform.runLater(() -> { - try { - TrackEvent.info("mode", "Setting up window ..."); - UnlockAlert.showIfNeeded(); - App.getApp().setupWindow(); - AppGreetings.showIfNeeded(); - UpdateChangelogAlert.showIfNeeded(); + if (AppMainWindow.getInstance() == null) { + try { + TrackEvent.info("mode", "Setting up window ..."); + UnlockAlert.showIfNeeded(); + App.getApp().setupWindow(); + AppGreetings.showIfNeeded(); + UpdateChangelogAlert.showIfNeeded(); + latch.countDown(); + } catch (Throwable t) { + ErrorEvent.fromThrowable(t).terminal(true).handle(); + } + } else { + AppMainWindow.getInstance().show(); latch.countDown(); - } catch (Throwable t) { - ErrorEvent.fromThrowable(t).terminal(true).handle(); } });