ask for permissions instead of exiting when the hook fails
This commit is contained in:
@@ -19,10 +19,15 @@ public class Main {
|
|||||||
LOGGER.info("Hello world!");
|
LOGGER.info("Hello world!");
|
||||||
|
|
||||||
useSystemLookAndFeel();
|
useSystemLookAndFeel();
|
||||||
registerJNativeHook();
|
boolean hookRegistered = registerJNativeHook();
|
||||||
|
|
||||||
// all Swing components must be created and updated on the EDT
|
// all Swing components must be created and updated on the EDT
|
||||||
SwingUtilities.invokeLater(mainWindow::init);
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
mainWindow.init();
|
||||||
|
if (!hookRegistered) {
|
||||||
|
mainWindow.showPermissionsHelp();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void useSystemLookAndFeel() {
|
private static void useSystemLookAndFeel() {
|
||||||
@@ -33,18 +38,22 @@ public class Main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerJNativeHook() {
|
private static boolean registerJNativeHook() {
|
||||||
LOGGER.info("Registering jnativehook library...");
|
LOGGER.info("Registering jnativehook library...");
|
||||||
try {
|
try {
|
||||||
GlobalScreen.registerNativeHook();
|
GlobalScreen.registerNativeHook();
|
||||||
GlobalScreen.addNativeKeyListener(new KeyPressListener());
|
GlobalScreen.addNativeKeyListener(new KeyPressListener());
|
||||||
LOGGER.info("Successfully registered jnativehook library!");
|
LOGGER.info("Successfully registered jnativehook library!");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
catch (NativeHookException ex) {
|
catch (NativeHookException ex) {
|
||||||
LOGGER.error("There was a problem registering the native hook.");
|
LOGGER.error("There was a problem registering the native hook.", ex);
|
||||||
LOGGER.error(ex.getMessage());
|
|
||||||
|
|
||||||
System.exit(1);
|
// without the accessibility permission the hotkey cannot be
|
||||||
|
// registered and the mouse cannot be moved either: the app would
|
||||||
|
// look alive but do nothing. don't exit: keep the window and the
|
||||||
|
// tray icon usable, and tell the user what is missing.
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import java.awt.*;
|
|||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
@@ -174,6 +175,46 @@ public class MainWindow
|
|||||||
Main.unregisterJNativeHook();
|
Main.unregisterJNativeHook();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Explains that the app cannot work without its permissions, and offers
|
||||||
|
* a shortcut to the right system settings pane. Must be called on the
|
||||||
|
* EDT, after the window is visible.
|
||||||
|
*/
|
||||||
|
public void showPermissionsHelp() {
|
||||||
|
Object[] options = {"Open System Settings", "Close"};
|
||||||
|
|
||||||
|
int choice = JOptionPane.showOptionDialog(frame,
|
||||||
|
"autosqueal needs the accessibility permission to move the mouse and to\n"
|
||||||
|
+ "listen for the ctrl+alt hotkey, and the screen recording one to\n"
|
||||||
|
+ "show the screen preview. they cannot be granted while it is running.\n\n"
|
||||||
|
+ "grant them in privacy & security, then restart autosqueal.",
|
||||||
|
"permissions needed",
|
||||||
|
JOptionPane.DEFAULT_OPTION,
|
||||||
|
JOptionPane.WARNING_MESSAGE,
|
||||||
|
null,
|
||||||
|
options,
|
||||||
|
options[0]);
|
||||||
|
|
||||||
|
if (choice == 0) {
|
||||||
|
openPrivacySettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Opens the privacy & security pane at the accessibility section. */
|
||||||
|
private void openPrivacySettings() {
|
||||||
|
if (SystemUtil.getHostSystem() != SystemUtil.OperatingSystem.MAC_OS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
new ProcessBuilder("open",
|
||||||
|
"x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility")
|
||||||
|
.start();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.error("Could not open the system settings", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggles the automation on or off. Safe to call from any thread: the actual
|
* Toggles the automation on or off. Safe to call from any thread: the actual
|
||||||
* work is always marshalled to the EDT, since it touches Swing components.
|
* work is always marshalled to the EDT, since it touches Swing components.
|
||||||
|
|||||||
Reference in New Issue
Block a user