diff --git a/common/src/main/java/bisq/common/util/DesktopUtil.java b/common/src/main/java/bisq/common/util/DesktopUtil.java index 6864af5b87..c75f5dc522 100644 --- a/common/src/main/java/bisq/common/util/DesktopUtil.java +++ b/common/src/main/java/bisq/common/util/DesktopUtil.java @@ -17,8 +17,6 @@ package bisq.common.util; -import java.awt.Desktop; - import java.net.URI; import java.io.File; @@ -27,17 +25,20 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import lombok.extern.slf4j.Slf4j; + // Taken form https://stackoverflow.com/questions/18004150/desktop-api-is-not-supported-on-the-current-platform, // originally net.mightypork.rpack.utils.DesktopApi +@Slf4j class DesktopUtil { public static boolean browse(URI uri) { - return openSystemSpecific(uri.toString()) || browseDESKTOP(uri); + return openSystemSpecific(uri.toString()); } public static boolean open(File file) { - return openSystemSpecific(file.getPath()) || openDESKTOP(file); + return openSystemSpecific(file.getPath()); } @@ -45,7 +46,7 @@ class DesktopUtil { // you can try something like // runCommand("gimp", "%s", file.getPath()) // based on user preferences. - return openSystemSpecific(file.getPath()) || editDESKTOP(file); + return openSystemSpecific(file.getPath()); } @@ -69,82 +70,10 @@ class DesktopUtil { } - private static boolean browseDESKTOP(URI uri) { - - logOut("Trying to use Desktop.getDesktop().browse() with " + uri.toString()); - try { - if (!Desktop.isDesktopSupported()) { - logErr("Platform is not supported."); - return false; - } - - if (!Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { - logErr("BROWSE is not supported."); - return false; - } - - Desktop.getDesktop().browse(uri); - - return true; - } catch (Throwable t) { - logErr("Error using desktop browse.", t); - return false; - } - } - - - private static boolean openDESKTOP(File file) { - - logOut("Trying to use Desktop.getDesktop().open() with " + file.toString()); - try { - if (!Desktop.isDesktopSupported()) { - logErr("Platform is not supported."); - return false; - } - - if (!Desktop.getDesktop().isSupported(Desktop.Action.OPEN)) { - logErr("OPEN is not supported."); - return false; - } - - Desktop.getDesktop().open(file); - - return true; - } catch (Throwable t) { - logErr("Error using desktop open.", t); - return false; - } - } - - - private static boolean editDESKTOP(File file) { - - logOut("Trying to use Desktop.getDesktop().edit() with " + file); - try { - if (!Desktop.isDesktopSupported()) { - logErr("Platform is not supported."); - return false; - } - - if (!Desktop.getDesktop().isSupported(Desktop.Action.EDIT)) { - logErr("EDIT is not supported."); - return false; - } - - Desktop.getDesktop().edit(file); - - return true; - } catch (Throwable t) { - logErr("Error using desktop edit.", t); - return false; - } - } - - @SuppressWarnings("SameParameterValue") private static boolean runCommand(String command, String args, String file) { - logOut("Trying to exec:\n cmd = " + command + "\n args = " + args + "\n %s = " + file); + log.info("Trying to exec: cmd = {} args = {} file = {}", command, args, file); String[] parts = prepareCommand(command, args, file); @@ -155,17 +84,17 @@ class DesktopUtil { try { int value = p.exitValue(); if (value == 0) { - logErr("Process ended immediately."); + log.warn("Process ended immediately."); } else { - logErr("Process crashed."); + log.warn("Process crashed."); } return false; } catch (IllegalThreadStateException e) { - logErr("Process is running."); + log.info("Process is running."); return true; } } catch (IOException e) { - logErr("Error running command.", e); + log.warn("Error running command. {}", e); return false; } } @@ -187,19 +116,6 @@ class DesktopUtil { return parts.toArray(new String[parts.size()]); } - private static void logErr(String msg, Throwable t) { - System.err.println(msg); - t.printStackTrace(); - } - - private static void logErr(String msg) { - System.err.println(msg); - } - - private static void logOut(String msg) { - System.out.println(msg); - } - public enum EnumOS { linux, macos, diff --git a/common/src/main/java/bisq/common/util/Utilities.java b/common/src/main/java/bisq/common/util/Utilities.java index a2b90f816e..64c7775720 100644 --- a/common/src/main/java/bisq/common/util/Utilities.java +++ b/common/src/main/java/bisq/common/util/Utilities.java @@ -76,9 +76,6 @@ import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import static java.awt.Desktop.Action; -import static java.awt.Desktop.getDesktop; -import static java.awt.Desktop.isDesktopSupported; @Slf4j public class Utilities { @@ -292,37 +289,13 @@ public class Utilities { } public static void openURI(URI uri) throws IOException { - if (!isLinux() - && isDesktopSupported() - && getDesktop().isSupported(Action.BROWSE)) { - getDesktop().browse(uri); - } else { - // Maybe Application.HostServices works in those cases? - // HostServices hostServices = getHostServices(); - // hostServices.showDocument(uri.toString()); - - // On Linux Desktop is poorly implemented. - // See https://stackoverflow.com/questions/18004150/desktop-api-is-not-supported-on-the-current-platform - if (!DesktopUtil.browse(uri)) - throw new IOException("Failed to open URI: " + uri.toString()); - } + if (!DesktopUtil.browse(uri)) + throw new IOException("Failed to open URI: " + uri.toString()); } public static void openFile(File file) throws IOException { - if (!isLinux() - && isDesktopSupported() - && getDesktop().isSupported(Action.OPEN)) { - getDesktop().open(file); - } else { - // Maybe Application.HostServices works in those cases? - // HostServices hostServices = getHostServices(); - // hostServices.showDocument(uri.toString()); - - // On Linux Desktop is poorly implemented. - // See https://stackoverflow.com/questions/18004150/desktop-api-is-not-supported-on-the-current-platform - if (!DesktopUtil.open(file)) - throw new IOException("Failed to open file: " + file.toString()); - } + if (!DesktopUtil.open(file)) + throw new IOException("Failed to open file: " + file.toString()); } public static String getDownloadOfHomeDir() { diff --git a/desktop/src/main/java/bisq/desktop/app/BisqApp.java b/desktop/src/main/java/bisq/desktop/app/BisqApp.java index d5c0ac46b2..8c1410a61b 100644 --- a/desktop/src/main/java/bisq/desktop/app/BisqApp.java +++ b/desktop/src/main/java/bisq/desktop/app/BisqApp.java @@ -56,6 +56,7 @@ import com.google.common.base.Joiner; import javafx.application.Application; import javafx.stage.Modality; +import javafx.stage.Screen; import javafx.stage.Stage; import javafx.stage.StageStyle; @@ -65,8 +66,7 @@ import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; import javafx.scene.layout.StackPane; -import java.awt.GraphicsEnvironment; -import java.awt.Rectangle; +import javafx.geometry.Rectangle2D; import java.util.ArrayList; import java.util.List; @@ -197,20 +197,21 @@ public class BisqApp extends Application implements UncaughtExceptionHandler { /////////////////////////////////////////////////////////////////////////////////////////// private Scene createAndConfigScene(MainView mainView, Injector injector) { - Rectangle maxWindowBounds = new Rectangle(); + //Rectangle maxWindowBounds = new Rectangle(); + Rectangle2D maxWindowBounds = new Rectangle2D(0, 0, 0, 0); try { - maxWindowBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds(); + maxWindowBounds = Screen.getPrimary().getBounds(); } catch (IllegalArgumentException e) { // Multi-screen environments may encounter IllegalArgumentException (Window must not be zero) // Just ignore the exception and continue, which means the window will use the minimum window size below // since we are unable to determine if we can use a larger size } Scene scene = new Scene(mainView.getRoot(), - maxWindowBounds.width < INITIAL_WINDOW_WIDTH ? - Math.max(maxWindowBounds.width, MIN_WINDOW_WIDTH) : + maxWindowBounds.getWidth() < INITIAL_WINDOW_WIDTH ? + Math.max(maxWindowBounds.getWidth(), MIN_WINDOW_WIDTH) : INITIAL_WINDOW_WIDTH, - maxWindowBounds.height < INITIAL_WINDOW_HEIGHT ? - Math.max(maxWindowBounds.height, MIN_WINDOW_HEIGHT) : + maxWindowBounds.getHeight() < INITIAL_WINDOW_HEIGHT ? + Math.max(maxWindowBounds.getHeight(), MIN_WINDOW_HEIGHT) : INITIAL_WINDOW_HEIGHT); addSceneKeyEventHandler(scene, injector); @@ -226,9 +227,6 @@ public class BisqApp extends Application implements UncaughtExceptionHandler { } private void setupStage(Scene scene) { - // configure the system tray - SystemTray.create(stage, shutDownHandler); - stage.setOnCloseRequest(event -> { event.consume(); shutDownByUser(); diff --git a/desktop/src/main/java/bisq/desktop/app/SystemTray.java b/desktop/src/main/java/bisq/desktop/app/SystemTray.java deleted file mode 100644 index d8dbf749a5..0000000000 --- a/desktop/src/main/java/bisq/desktop/app/SystemTray.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.desktop.app; - -import bisq.desktop.util.GUIUtil; -import bisq.desktop.util.ImageUtil; - -import bisq.common.BisqException; -import bisq.core.locale.Res; - -import bisq.common.UserThread; -import bisq.common.util.Utilities; - -import javafx.application.Platform; - -import javafx.stage.Stage; - -import java.awt.AWTException; -import java.awt.Image; -import java.awt.MenuItem; -import java.awt.PopupMenu; -import java.awt.TrayIcon; -import java.awt.image.BufferedImage; - -import javax.imageio.ImageIO; - -import java.io.IOException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * There is no JavaFX support yet, so we need to use AWT. - */ -public class SystemTray { - private static final Logger log = LoggerFactory.getLogger(SystemTray.class); - - private static final String ICON_HI_RES = "/images/system_tray_icon@2x.png"; - private static final String ICON_LO_RES = "/images/system_tray_icon.png"; - private static final String ICON_HI_RES_WHITE = "/images/system_tray_icon@2x_white.png"; - private static final String ICON_LO_RES_WHITE = "/images/system_tray_icon_white.png"; - private static final String ICON_WINDOWS_LO_RES = "/images/system_tray_icon_windows.png"; - private static final String ICON_WINDOWS_HI_RES = "/images/system_tray_icon_windows@2x.png"; - private static final String ICON_LINUX = "/images/system_tray_icon_linux.png"; - - - private static final String SHOW_WINDOW_LABEL = Res.get("systemTray.show"); - private static final String HIDE_WINDOW_LABEL = Res.get("systemTray.hide"); - - private final Stage stage; - private final Runnable onExit; - private final MenuItem toggleShowHideItem = new MenuItem(HIDE_WINDOW_LABEL); - - public static void create(Stage stage, Runnable onExit) { - new SystemTray(stage, onExit); - } - - private SystemTray(Stage stage, Runnable onExit) { - this.stage = stage; - this.onExit = onExit; - init(); - } - - private void init() { - if (!java.awt.SystemTray.isSupported()) { - log.error("System tray is not supported."); - return; - } - - // prevent exiting the app when the last window gets closed - // For now we allow to close the app by closing the window. - // Later we only let it close via the system trays exit. - Platform.setImplicitExit(false); - - MenuItem aboutItem = new MenuItem(Res.get("systemTray.info")); - MenuItem exitItem = new MenuItem(Res.get("systemTray.exit")); - - PopupMenu popupMenu = new PopupMenu(); - popupMenu.add(aboutItem); - popupMenu.addSeparator(); - popupMenu.add(toggleShowHideItem); - popupMenu.addSeparator(); - popupMenu.add(exitItem); - - String path; - if (Utilities.isOSX()) - if (Utilities.isMacMenuBarDarkMode()) - path = ImageUtil.isRetina() ? ICON_HI_RES_WHITE : ICON_LO_RES_WHITE; - else - path = ImageUtil.isRetina() ? ICON_HI_RES : ICON_LO_RES; - - else if (Utilities.isWindows()) - path = ImageUtil.isRetina() ? ICON_WINDOWS_HI_RES : ICON_WINDOWS_LO_RES; - else - path = ICON_LINUX; - - try { - BufferedImage trayIconImage = ImageIO.read(getClass().getResource(path)); - TrayIcon trayIcon = new TrayIcon(trayIconImage); - // On Windows and Linux the icon needs to be resized - // On macOS we get the correct size from the provided image - if (!Utilities.isOSX()) { - if (ImageUtil.isRetina()) { - // Using auto sizing provides better results with high resolution - trayIcon.setImageAutoSize(true); - } else { - // Using scaling provides better results with low resolution - trayIcon = new TrayIcon(trayIconImage.getScaledInstance(trayIcon.getSize().width, -1, Image.SCALE_SMOOTH)); - } - } - - trayIcon.setPopupMenu(popupMenu); - trayIcon.setToolTip(Res.get("systemTray.tooltip")); - - java.awt.SystemTray.getSystemTray().add(trayIcon); - } catch (AWTException e1) { - log.error("Icon could not be added to system tray.", e1); - } catch (IOException e2) { - throw new BisqException(e2); - } - - toggleShowHideItem.addActionListener(e -> { - if (stage.isShowing()) { - toggleShowHideItem.setLabel(SHOW_WINDOW_LABEL); - UserThread.execute(stage::hide); - } else { - toggleShowHideItem.setLabel(HIDE_WINDOW_LABEL); - UserThread.execute(stage::show); - } - }); - - aboutItem.addActionListener(e -> { - try { - UserThread.execute(() -> GUIUtil.openWebPage("https://bisq.network")); - } catch (Exception e1) { - e1.printStackTrace(); - } - }); - exitItem.addActionListener(e -> UserThread.execute(onExit::run)); - } - - public void hideStage() { - stage.hide(); - toggleShowHideItem.setLabel(SHOW_WINDOW_LABEL); - } - -} diff --git a/desktop/src/main/java/bisq/desktop/util/ImageUtil.java b/desktop/src/main/java/bisq/desktop/util/ImageUtil.java index 948dee3209..1568f449ab 100644 --- a/desktop/src/main/java/bisq/desktop/util/ImageUtil.java +++ b/desktop/src/main/java/bisq/desktop/util/ImageUtil.java @@ -21,13 +21,11 @@ import bisq.core.locale.Country; import bisq.common.util.Utilities; +import javafx.stage.Screen; + import javafx.scene.image.Image; import javafx.scene.image.ImageView; -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsEnvironment; -import java.awt.geom.AffineTransform; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,9 +70,9 @@ public class ImageUtil { } } + // determine if this is a MacOS retina display + // https://stackoverflow.com/questions/20767708/how-do-you-detect-a-retina-display-in-java#20767802 public static boolean isRetina() { - final GraphicsConfiguration gfxConfig = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); - final AffineTransform transform = gfxConfig.getDefaultTransform(); - return !transform.isIdentity(); + return Screen.getPrimary().getOutputScaleX() > 1.5; } }