mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-08-18 21:26:02 +00:00
Make Cryptomator a foreground app when restoring from status bar icon
This commit is contained in:
@@ -8,11 +8,13 @@
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.ui;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.cryptomator.ui.controllers.MainController;
|
||||
import org.cryptomator.ui.jni.MacFunctions;
|
||||
import org.cryptomator.ui.settings.Localization;
|
||||
import org.cryptomator.ui.util.AsyncTaskService;
|
||||
import org.cryptomator.ui.util.DeferredCloser;
|
||||
@@ -34,4 +36,6 @@ interface CryptomatorComponent {
|
||||
Localization localization();
|
||||
|
||||
ExitUtil exitUtil();
|
||||
|
||||
Optional<MacFunctions> nativeMacFunctions();
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import org.cryptomator.crypto.engine.impl.CryptoEngineModule;
|
||||
import org.cryptomator.frontend.FrontendFactory;
|
||||
import org.cryptomator.frontend.webdav.WebDavModule;
|
||||
import org.cryptomator.frontend.webdav.WebDavServer;
|
||||
import org.cryptomator.ui.jni.JniModule;
|
||||
import org.cryptomator.ui.model.VaultObjectMapperProvider;
|
||||
import org.cryptomator.ui.settings.Settings;
|
||||
import org.cryptomator.ui.settings.SettingsProvider;
|
||||
@@ -33,7 +34,7 @@ import dagger.Provides;
|
||||
import javafx.application.Application;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
@Module(includes = {CryptoEngineModule.class, CommonsModule.class, WebDavModule.class})
|
||||
@Module(includes = {CryptoEngineModule.class, CommonsModule.class, WebDavModule.class, JniModule.class})
|
||||
class CryptomatorModule {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CryptomatorModule.class);
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -32,6 +33,8 @@ import javax.script.ScriptException;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.ui.jni.JniException;
|
||||
import org.cryptomator.ui.jni.MacFunctions;
|
||||
import org.cryptomator.ui.settings.Localization;
|
||||
import org.cryptomator.ui.settings.Settings;
|
||||
import org.slf4j.Logger;
|
||||
@@ -48,12 +51,14 @@ class ExitUtil {
|
||||
private final Stage mainWindow;
|
||||
private final Localization localization;
|
||||
private final Settings settings;
|
||||
private final Optional<MacFunctions> macFunctions;
|
||||
|
||||
@Inject
|
||||
public ExitUtil(@Named("mainWindow") Stage mainWindow, Localization localization, Settings settings) {
|
||||
public ExitUtil(@Named("mainWindow") Stage mainWindow, Localization localization, Settings settings, Optional<MacFunctions> macFunctions) {
|
||||
this.mainWindow = mainWindow;
|
||||
this.localization = localization;
|
||||
this.settings = settings;
|
||||
this.macFunctions = macFunctions;
|
||||
}
|
||||
|
||||
public void initExitHandler(Runnable exitCommand) {
|
||||
@@ -88,6 +93,7 @@ class ExitUtil {
|
||||
if (Platform.isImplicitExit()) {
|
||||
exitCommand.run();
|
||||
} else {
|
||||
macFunctions.ifPresent(JniException.ignore(MacFunctions::transformToAgentApplication));
|
||||
mainWindow.close();
|
||||
this.showTrayNotification(trayIcon);
|
||||
}
|
||||
@@ -189,6 +195,7 @@ class ExitUtil {
|
||||
|
||||
private void restoreFromTray(ActionEvent event) {
|
||||
Platform.runLater(() -> {
|
||||
macFunctions.ifPresent(JniException.ignore(MacFunctions::transformToForegroundApplication));
|
||||
mainWindow.show();
|
||||
mainWindow.requestFocus();
|
||||
});
|
||||
|
||||
@@ -16,6 +16,8 @@ import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.ui.controllers.MainController;
|
||||
import org.cryptomator.ui.jni.JniException;
|
||||
import org.cryptomator.ui.jni.MacFunctions;
|
||||
import org.cryptomator.ui.util.ActiveWindowStyleSupport;
|
||||
import org.cryptomator.ui.util.DeferredCloser;
|
||||
import org.cryptomator.ui.util.SingleInstanceManager;
|
||||
@@ -67,6 +69,7 @@ public class MainApplication extends Application {
|
||||
}
|
||||
|
||||
// show window and start observing its focus:
|
||||
comp.nativeMacFunctions().ifPresent(JniException.ignore(MacFunctions::transformToForegroundApplication));
|
||||
primaryStage.show();
|
||||
ActiveWindowStyleSupport.startObservingFocus(primaryStage);
|
||||
comp.exitUtil().initExitHandler(this::quit);
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.cryptomator.ui.jni;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Thrown to indicate that a JNI call didn't succeed, i.e. returned an unexpected return value.
|
||||
*/
|
||||
public class JniException extends RuntimeException {
|
||||
|
||||
protected JniException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public static <T> Consumer<T> ignore(Consumer<T> consumer) {
|
||||
return value -> {
|
||||
try {
|
||||
consumer.accept(value);
|
||||
} catch (RuntimeException e) {
|
||||
// no-op
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.cryptomator.ui.jni;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
@Module
|
||||
public class JniModule {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JniModule.class);
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
Optional<MacFunctions> provideMacFunctions(MacFunctions macFunctions) {
|
||||
if (SystemUtils.IS_OS_MAC) {
|
||||
try {
|
||||
System.loadLibrary("MacFunctions");
|
||||
return Optional.of(macFunctions);
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
LOG.error("Could not load JNI lib from path {}", System.getProperty("java.library.path"));
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.cryptomator.ui.jni;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class MacFunctions {
|
||||
|
||||
@Inject
|
||||
MacFunctions() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the current application a foreground application, which appears in the Dock and the Application Switcher.
|
||||
*/
|
||||
public void transformToForegroundApplication() {
|
||||
int errorCode = transformToForegroundApplication0();
|
||||
if (errorCode != 0) {
|
||||
throw new JniException("Failed to make app a foreground app. Error code " + errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
private native int transformToForegroundApplication0();
|
||||
|
||||
/**
|
||||
* Makes the current application an agent app. Agent apps do not appear in the Dock or in the Force Quit window.
|
||||
*/
|
||||
public void transformToAgentApplication() {
|
||||
int errorCode = transformToAgentApplication0();
|
||||
if (errorCode != 0) {
|
||||
throw new JniException("Failed to make app an agent app. Error code " + errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
private native int transformToAgentApplication0();
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user