macOS: Only show application menu and dock icon when a Window is visible (related to #957, #283, #346, #62)

This commit is contained in:
Sebastian Stenzel
2019-08-26 18:03:26 +02:00
parent 282b80fe24
commit 264e81b4a0
6 changed files with 47 additions and 11 deletions

View File

@@ -3,11 +3,16 @@ package org.cryptomator.ui.fxapp;
import dagger.Lazy;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableSet;
import javafx.stage.Stage;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.UiTheme;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.jni.MacApplicationUiState;
import org.cryptomator.jni.MacFunctions;
import org.cryptomator.ui.mainwindow.MainWindowComponent;
import org.cryptomator.ui.preferences.PreferencesComponent;
@@ -31,6 +36,8 @@ public class FxApplication extends Application {
private final UnlockComponent.Builder unlockWindowBuilder;
private final QuitComponent.Builder quitWindowBuilder;
private final Optional<MacFunctions> macFunctions;
private final ObservableSet<Stage> visibleStages = FXCollections.observableSet();
private final BooleanBinding hasVisibleStages = Bindings.isNotEmpty(visibleStages);
@Inject
FxApplication(Settings settings, Lazy<MainWindowComponent> mainWindow, Lazy<PreferencesComponent> preferencesWindow, UnlockComponent.Builder unlockWindowBuilder, QuitComponent.Builder quitWindowBuilder, Optional<MacFunctions> macFunctions) {
@@ -46,6 +53,8 @@ public class FxApplication extends Application {
LOG.trace("FxApplication.start()");
Platform.setImplicitExit(false);
hasVisibleStages.addListener(this::hasVisibleStagesChanged);
settings.theme().addListener(this::themeChanged);
loadSelectedStyleSheet(settings.theme().get());
}
@@ -55,30 +64,47 @@ public class FxApplication extends Application {
throw new UnsupportedOperationException("Use start() instead.");
}
private void addVisibleStage(Stage stage) {
visibleStages.add(stage);
stage.setOnHidden(evt -> visibleStages.remove(stage));
}
private void hasVisibleStagesChanged(@SuppressWarnings("unused") ObservableValue<? extends Boolean> observableValue, @SuppressWarnings("unused") boolean oldValue, boolean newValue) {
if (newValue) {
macFunctions.map(MacFunctions::uiState).ifPresent(MacApplicationUiState::transformToForegroundApplication);
} else {
macFunctions.map(MacFunctions::uiState).ifPresent(MacApplicationUiState::transformToAgentApplication);
}
}
public void showPreferencesWindow() {
Platform.runLater(() -> {
preferencesWindow.get().showPreferencesWindow();
Stage stage = preferencesWindow.get().showPreferencesWindow();
addVisibleStage(stage);
LOG.debug("Showing Preferences");
});
}
public void showMainWindow() {
Platform.runLater(() -> {
mainWindow.get().showMainWindow();
Stage stage = mainWindow.get().showMainWindow();
addVisibleStage(stage);
LOG.debug("Showing MainWindow");
});
}
public void showUnlockWindow(Vault vault) {
Platform.runLater(() -> {
unlockWindowBuilder.vault(vault).build().showUnlockWindow();
Stage stage = unlockWindowBuilder.vault(vault).build().showUnlockWindow();
addVisibleStage(stage);
LOG.debug("Showing UnlockWindow for {}", vault.getDisplayableName());
});
}
public void showQuitWindow(QuitResponse response) {
Platform.runLater(() -> {
quitWindowBuilder.quitResponse(response).build().showQuitWindow();
Stage stage = quitWindowBuilder.quitResponse(response).build().showQuitWindow();
addVisibleStage(stage);
LOG.debug("Showing QuitWindow");
});
}

View File

@@ -22,11 +22,12 @@ public interface MainWindowComponent {
@FxmlScene(FxmlFile.MAIN_WINDOW)
Lazy<Scene> scene();
default void showMainWindow() {
default Stage showMainWindow() {
Stage stage = window();
stage.setScene(scene().get());
stage.show();
stage.requestFocus();
return stage;
}
@Subcomponent.Builder

View File

@@ -23,11 +23,12 @@ public interface PreferencesComponent {
@FxmlScene(FxmlFile.PREFERENCES)
Lazy<Scene> scene();
default void showPreferencesWindow() {
default Stage showPreferencesWindow() {
Stage stage = window();
stage.setScene(scene().get());
stage.show();
stage.requestFocus();
return stage;
}
@Subcomponent.Builder

View File

@@ -25,11 +25,12 @@ public interface QuitComponent {
@FxmlScene(FxmlFile.QUIT)
Lazy<Scene> scene();
default void showQuitWindow() {
default Stage showQuitWindow() {
Stage stage = window();
stage.setScene(scene().get());
stage.show();
stage.requestFocus();
return stage;
}
@Subcomponent.Builder

View File

@@ -3,6 +3,9 @@ package org.cryptomator.ui.traymenu;
import javafx.beans.Observable;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.jni.JniException;
import org.cryptomator.jni.MacApplicationUiState;
import org.cryptomator.jni.MacFunctions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -10,6 +13,7 @@ import javax.inject.Inject;
import java.awt.AWTException;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.util.Optional;
@TrayMenuScoped
public class TrayIconController {
@@ -20,15 +24,15 @@ public class TrayIconController {
private final TrayImageFactory imageFactory;
private final TrayMenuController trayMenuController;
private final TrayIcon trayIcon;
// private final Optional<MacFunctions> macFunctions;
private final Optional<MacFunctions> macFunctions;
@Inject
TrayIconController(Settings settings, TrayImageFactory imageFactory, TrayMenuController trayMenuController) {
TrayIconController(Settings settings, TrayImageFactory imageFactory, TrayMenuController trayMenuController, Optional<MacFunctions> macFunctions) {
this.settings = settings;
this.trayMenuController = trayMenuController;
this.imageFactory = imageFactory;
this.trayIcon = new TrayIcon(imageFactory.loadImage(), "Cryptomator", trayMenuController.getMenu());
// this.macFunctions = macFunctions;
this.macFunctions = macFunctions;
}
public void initializeTrayIcon() {
@@ -38,6 +42,8 @@ public class TrayIconController {
if (SystemUtils.IS_OS_WINDOWS) {
// TODO: test on windows: is this a double click?
trayIcon.addActionListener(trayMenuController::showMainWindow);
} else if (SystemUtils.IS_OS_MAC) {
macFunctions.map(MacFunctions::uiState).ifPresent(JniException.ignore(MacApplicationUiState::transformToAgentApplication));
}
try {

View File

@@ -24,10 +24,11 @@ public interface UnlockComponent {
@FxmlScene(FxmlFile.UNLOCK)
Lazy<Scene> scene();
default void showUnlockWindow() {
default Stage showUnlockWindow() {
Stage stage = window();
stage.setScene(scene().get());
stage.show();
return stage;
}
@Subcomponent.Builder