-
Notifications
You must be signed in to change notification settings - Fork 810
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Over-engineer the launch warning beyond reason
- Loading branch information
1 parent
7ad9414
commit 9c045da
Showing
7 changed files
with
235 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,7 +50,6 @@ sourceSets { | |
launchWarn { | ||
java { | ||
srcDir "src/desktop/java" | ||
include "**/LaunchWarn.java" | ||
} | ||
} | ||
} | ||
|
172 changes: 140 additions & 32 deletions
172
src/desktop/java/net/caffeinemc/mods/sodium/desktop/LaunchWarn.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,48 +1,156 @@ | ||
package net.caffeinemc.mods.sodium.desktop; | ||
|
||
import javax.swing.JOptionPane; | ||
import javax.swing.UIManager; | ||
import javax.swing.UnsupportedLookAndFeelException; | ||
import java.awt.Desktop; | ||
import java.awt.GraphicsEnvironment; | ||
import net.caffeinemc.mods.sodium.desktop.utils.browse.BrowseUrlHandler; | ||
|
||
import javax.swing.*; | ||
import java.awt.*; | ||
import java.io.IOException; | ||
import java.net.URI; | ||
|
||
/** | ||
* Taken from | ||
* https://github.com/IrisShaders/Iris/blob/6c880cd377d97ffd5de648ba4dfac7ea88897b4f/src/main/java/net/coderbot/iris/LaunchWarn.java | ||
* and modified to fit Sodium. See Iris' license for more information. | ||
*/ | ||
public class LaunchWarn { | ||
private static final String HELP_URL = "https://github.com/CaffeineMC/sodium-fabric/wiki/Installation"; | ||
|
||
private static final String RICH_MESSAGE = | ||
"<html>" + | ||
"<body>" + | ||
"<p style='width: 600px; padding: 0 0 8px 0;'>" + | ||
"You have tried to launch Sodium (a Minecraft mod) directly, but it is not an executable program or mod installer. Instead, " + | ||
"you must install Fabric Loader for Minecraft, and then place this file in your mods directory." + | ||
"</p>" + | ||
"<p style='width: 600px; padding: 0 0 8px 0;'>" + | ||
"If this is your first time installing mods with Fabric Loader, then click the \"Help\" button for an installation guide." + | ||
"</p>" + | ||
"</body>" + | ||
"</html>"; | ||
|
||
private static final String FALLBACK_MESSAGE = | ||
"<html>" + | ||
"<body>" + | ||
"<p style='width: 600px; padding: 0 0 8px 0;'>" + | ||
"You have tried to launch Sodium (a Minecraft mod) directly, but it is not an executable program or mod installer. Instead, " + | ||
"you must install Fabric Loader for Minecraft, and then place this file in your mods directory." + | ||
"</p>" + | ||
"<p style='width: 600px; padding: 0 0 8px 0;'>" + | ||
"If this is your first time installing mods with Fabric Loader, then visit <i>" + HELP_URL + "</i> for an installation guide." + | ||
"</p>" + | ||
"</body>" + | ||
"</html>"; | ||
|
||
private static final String FAILED_TO_BROWSE_MESSAGE = | ||
"<html>" + | ||
"<body>" + | ||
"<p style='width: 400px; padding: 0 0 8px 0;'>" + | ||
"Failed to open the default browser! Your system may be misconfigured. Please open the URL <i>" + HELP_URL + "</i> manually." + | ||
"</p>" + | ||
"</body>" + | ||
"</html>"; | ||
public static final String WINDOW_TITLE = "Sodium"; | ||
|
||
public static void main(String[] args) { | ||
String message = "You have tried to launch Sodium (a Minecraft mod) directly, but it is not an executable program or mod installer. You must install Fabric Loader for Minecraft, and place this file in your mods directory instead.\nIf this is your first time installing mods for Fabric Loader, click \"Help\" for a guide on how to do this."; | ||
String fallback = "You have tried to launch Sodium (a Minecraft mod) directly, but it is not an executable program or mod installer. You must install Fabric Loader for Minecraft, and place this file in your mods directory instead.\nIf this is your first time installing mods for Fabric Loader, open \"https://github.com/CaffeineMC/sodium-fabric/wiki/Installation\" for a guide on how to do this."; | ||
if (GraphicsEnvironment.isHeadless()) { | ||
System.err.println(fallback); | ||
showHeadlessError(); | ||
} else { | ||
showGraphicalError(); | ||
} | ||
} | ||
|
||
private static void showHeadlessError() { | ||
System.err.println(FALLBACK_MESSAGE); | ||
} | ||
|
||
private static void showGraphicalError() { | ||
trySetSystemLookAndFeel(); | ||
trySetSystemFontPreferences(); | ||
|
||
BrowseUrlHandler browseUrlHandler = BrowseUrlHandler.createImplementation(); | ||
|
||
if (browseUrlHandler != null) { | ||
showRichGraphicalDialog(browseUrlHandler); | ||
} else { | ||
showFallbackGraphicalDialog(); | ||
} | ||
|
||
System.exit(0); | ||
} | ||
|
||
private static void showRichGraphicalDialog(BrowseUrlHandler browseUrlHandler) { | ||
int selectedOption = showDialogBox(RICH_MESSAGE, WINDOW_TITLE, JOptionPane.YES_NO_OPTION, | ||
JOptionPane.INFORMATION_MESSAGE, new String[] { "Help", "Close" }, JOptionPane.YES_OPTION); | ||
|
||
if (selectedOption == JOptionPane.YES_OPTION) { | ||
log("Opening URL: " + HELP_URL); | ||
|
||
try { | ||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); | ||
} catch (ReflectiveOperationException | UnsupportedLookAndFeelException ignored) { | ||
// Ignored | ||
browseUrlHandler.browseTo(HELP_URL); | ||
} catch (IOException e) { | ||
log("Failed to open default web browser!", e); | ||
|
||
showDialogBox(FAILED_TO_BROWSE_MESSAGE, WINDOW_TITLE, JOptionPane.DEFAULT_OPTION, | ||
JOptionPane.WARNING_MESSAGE, null, JOptionPane.DEFAULT_OPTION); | ||
} | ||
} | ||
} | ||
|
||
if (Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { | ||
int option = JOptionPane.showOptionDialog(null, message, "Sodium", JOptionPane.YES_NO_OPTION, | ||
JOptionPane.INFORMATION_MESSAGE, null, new Object[] { "Help", "Cancel" }, JOptionPane.YES_OPTION); | ||
|
||
if (option == JOptionPane.YES_OPTION) { | ||
try { | ||
Desktop.getDesktop().browse(URI.create("https://github.com/CaffeineMC/sodium-fabric/wiki/Installation")); | ||
} catch (IOException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
} else { | ||
// Fallback for Linux, etc users with no "default" browser | ||
JOptionPane.showMessageDialog(null, fallback); | ||
private static void showFallbackGraphicalDialog() { | ||
// Fallback for Linux, etc users with no "default" browser | ||
showDialogBox(FALLBACK_MESSAGE, WINDOW_TITLE, JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, null); | ||
} | ||
|
||
private static int showDialogBox(String message, | ||
String title, | ||
int optionType, | ||
int messageType, | ||
String[] options, | ||
Object initialValue) { | ||
JOptionPane pane = new JOptionPane(message, messageType, optionType, null, options, initialValue); | ||
|
||
JDialog dialog = pane.createDialog(title); | ||
dialog.setVisible(true); | ||
|
||
Object selectedValue = pane.getValue(); | ||
|
||
if (selectedValue == null) { | ||
return JOptionPane.CLOSED_OPTION; | ||
} | ||
|
||
// If there is not an array of option buttons: | ||
if (options == null) { | ||
if (selectedValue instanceof Integer) { | ||
return (Integer) selectedValue; | ||
} | ||
|
||
return JOptionPane.CLOSED_OPTION; | ||
} | ||
|
||
System.exit(0); | ||
// If there is an array of option buttons: | ||
for (int counter = 0; counter < options.length; counter++) { | ||
String option = options[counter]; | ||
|
||
if (option.equals(selectedValue)) { | ||
return counter; | ||
} | ||
} | ||
|
||
return JOptionPane.CLOSED_OPTION; | ||
} | ||
|
||
private static void trySetSystemLookAndFeel() { | ||
try { | ||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); | ||
} catch (ReflectiveOperationException | UnsupportedLookAndFeelException ignored) { | ||
// Ignored | ||
} | ||
} | ||
|
||
private static void trySetSystemFontPreferences() { | ||
System.setProperty("awt.useSystemAAFontSettings", "on"); // Why is this not a default? | ||
} | ||
|
||
private static void log(String message) { | ||
System.err.println(message); | ||
} | ||
|
||
private static void log(String message, Throwable exception) { | ||
System.err.println(message); | ||
exception.printStackTrace(System.err); | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/BrowseUrlHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package net.caffeinemc.mods.sodium.desktop.utils.browse; | ||
|
||
import java.io.IOException; | ||
|
||
public interface BrowseUrlHandler { | ||
void browseTo(String url) throws IOException; | ||
|
||
static BrowseUrlHandler createImplementation() { | ||
// OpenJDK doesn't use xdg-open and fails to provide an implementation on most systems. | ||
if (XDGImpl.isSupported()) { | ||
// Apparently xdg-open is just broken for some desktop environments, because *for some reason* | ||
// setting a default browser is complicated. | ||
if (KDEImpl.isSupported()) { | ||
return new KDEImpl(); | ||
} else if (GNOMEImpl.isSupported()) { | ||
return new GNOMEImpl(); | ||
} | ||
|
||
// If the user's desktop environment isn't KDE or GNOME, then we can only rely on xdg-open being present. | ||
return new XDGImpl(); | ||
} else if (CrossPlatformImpl.isSupported()) { | ||
return new CrossPlatformImpl(); | ||
} | ||
|
||
return null; | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/CrossPlatformImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package net.caffeinemc.mods.sodium.desktop.utils.browse; | ||
|
||
import java.awt.*; | ||
import java.io.IOException; | ||
import java.net.URI; | ||
|
||
class CrossPlatformImpl implements BrowseUrlHandler { | ||
public static boolean isSupported() { | ||
return Desktop.getDesktop() | ||
.isSupported(Desktop.Action.BROWSE); | ||
} | ||
|
||
@Override | ||
public void browseTo(String url) throws IOException { | ||
Desktop.getDesktop().browse(URI.create(url)); | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/GNOMEImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package net.caffeinemc.mods.sodium.desktop.utils.browse; | ||
|
||
import java.io.IOException; | ||
|
||
class GNOMEImpl implements BrowseUrlHandler { | ||
public static boolean isSupported() { | ||
return XDGImpl.isSupported() && System.getenv("XDG_CURRENT_DESKTOP").equals("GNOME"); | ||
} | ||
|
||
@Override | ||
public void browseTo(String url) throws IOException { | ||
Runtime.getRuntime() | ||
.exec(new String[] { "gnome-open", url }); | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/KDEImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package net.caffeinemc.mods.sodium.desktop.utils.browse; | ||
|
||
import java.io.IOException; | ||
|
||
class KDEImpl implements BrowseUrlHandler { | ||
public static boolean isSupported() { | ||
return XDGImpl.isSupported() && System.getenv("XDG_CURRENT_DESKTOP").equals("KDE"); | ||
} | ||
|
||
@Override | ||
public void browseTo(String url) throws IOException { | ||
Runtime.getRuntime() | ||
.exec(new String[] { "kde-open", url }); | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
src/desktop/java/net/caffeinemc/mods/sodium/desktop/utils/browse/XDGImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package net.caffeinemc.mods.sodium.desktop.utils.browse; | ||
|
||
import net.caffeinemc.mods.sodium.desktop.utils.browse.BrowseUrlHandler; | ||
|
||
import java.io.IOException; | ||
import java.util.Locale; | ||
|
||
class XDGImpl implements BrowseUrlHandler { | ||
public static boolean isSupported() { | ||
String os = System.getProperty("os.name") | ||
.toLowerCase(Locale.ROOT); | ||
|
||
return os.equals("linux"); | ||
} | ||
|
||
@Override | ||
public void browseTo(String url) throws IOException { | ||
Runtime.getRuntime() | ||
.exec(new String[] { "xdg-open", url }); | ||
} | ||
} |