Skip to content

Commit 241c9c4

Browse files
authored
修复 FXUtils 意外的被提前初始化的问题 (HMCL-dev#6421)
1 parent 4b36f8c commit 241c9c4

6 files changed

Lines changed: 157 additions & 151 deletions

File tree

HMCL/src/main/java/org/jackhuang/hmcl/EntryPoint.java

Lines changed: 2 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,21 @@
1717
*/
1818
package org.jackhuang.hmcl;
1919

20-
import org.jackhuang.hmcl.setting.SambaException;
21-
import org.jackhuang.hmcl.setting.SettingsManager;
2220
import org.jackhuang.hmcl.util.FileSaver;
2321
import org.jackhuang.hmcl.util.SelfDependencyPatcher;
2422
import org.jackhuang.hmcl.util.SwingUtils;
2523
import org.jackhuang.hmcl.java.JavaRuntime;
2624
import org.jackhuang.hmcl.util.io.FileUtils;
2725
import org.jackhuang.hmcl.util.io.JarUtils;
28-
import org.jackhuang.hmcl.util.platform.CommandBuilder;
2926
import org.jackhuang.hmcl.util.platform.OperatingSystem;
3027

3128
import javax.swing.JOptionPane;
32-
import java.awt.Toolkit;
33-
import java.awt.datatransfer.StringSelection;
3429
import java.io.IOException;
3530
import java.lang.invoke.MethodHandle;
3631
import java.lang.invoke.MethodHandles;
3732
import java.lang.invoke.MethodType;
3833
import java.nio.file.Files;
3934
import java.nio.file.Path;
40-
import java.nio.file.Paths;
41-
import java.util.ArrayList;
4235
import java.util.concurrent.CancellationException;
4336

4437
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
@@ -59,8 +52,6 @@ public static void main(String[] args) {
5952

6053
checkWine();
6154

62-
setupJavaFXVMOptions();
63-
6455
if (OperatingSystem.CURRENT_OS == OperatingSystem.MACOS) {
6556
System.getProperties().putIfAbsent("apple.awt.application.appearance", "system");
6657
if (!isInsideMacAppBundle())
@@ -72,17 +63,6 @@ public static void main(String[] args) {
7263
addEnableNativeAccess();
7364
enableUnsafeMemoryAccess();
7465

75-
try {
76-
SettingsManager.init();
77-
} catch (SambaException e) {
78-
showWarning(i18n("fatal.samba"));
79-
} catch (IOException e) {
80-
LOG.error("Failed to load config", e);
81-
checkConfigOwner();
82-
SwingUtils.showErrorDialog(i18n("fatal.config_loading_failure", SettingsManager.localConfigDirectory()));
83-
EntryPoint.exit(1);
84-
}
85-
8666
Launcher.main(args);
8767
}
8868

@@ -92,71 +72,6 @@ public static void exit(int exitCode) {
9272
System.exit(exitCode);
9373
}
9474

95-
private static void setupJavaFXVMOptions() {
96-
if ("true".equalsIgnoreCase(System.getenv("HMCL_FORCE_GPU"))) {
97-
LOG.info("HMCL_FORCE_GPU: true");
98-
System.getProperties().putIfAbsent("prism.forceGPU", "true");
99-
}
100-
101-
String animationFrameRate = System.getenv("HMCL_ANIMATION_FRAME_RATE");
102-
if (animationFrameRate != null) {
103-
LOG.info("HMCL_ANIMATION_FRAME_RATE: " + animationFrameRate);
104-
105-
try {
106-
if (Integer.parseInt(animationFrameRate) <= 0)
107-
throw new NumberFormatException(animationFrameRate);
108-
109-
System.getProperties().putIfAbsent("javafx.animation.pulse", animationFrameRate);
110-
} catch (NumberFormatException e) {
111-
LOG.warning("Invalid animation frame rate: " + animationFrameRate);
112-
}
113-
}
114-
115-
String uiScale = System.getProperty("hmcl.uiScale", System.getenv("HMCL_UI_SCALE"));
116-
if (uiScale != null) {
117-
uiScale = uiScale.trim();
118-
119-
LOG.info("HMCL_UI_SCALE: " + uiScale);
120-
121-
try {
122-
float scaleValue;
123-
if (uiScale.endsWith("%")) {
124-
scaleValue = Integer.parseInt(uiScale.substring(0, uiScale.length() - 1)) / 100.0f;
125-
} else if (uiScale.endsWith("dpi") || uiScale.endsWith("DPI")) {
126-
scaleValue = Integer.parseInt(uiScale.substring(0, uiScale.length() - 3)) / 96.0f;
127-
} else {
128-
scaleValue = Float.parseFloat(uiScale);
129-
}
130-
131-
float lowerBound;
132-
float upperBound;
133-
134-
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) {
135-
// JavaFX behavior may be abnormal when the DPI scaling factor is too high
136-
lowerBound = 0.25f;
137-
upperBound = 4f;
138-
} else {
139-
lowerBound = 0.01f;
140-
upperBound = 10f;
141-
}
142-
143-
if (scaleValue >= lowerBound && scaleValue <= upperBound) {
144-
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) {
145-
System.getProperties().putIfAbsent("glass.win.uiScale", uiScale);
146-
} else if (OperatingSystem.CURRENT_OS == OperatingSystem.MACOS) {
147-
LOG.warning("macOS does not support setting UI scale, so it will be ignored");
148-
} else {
149-
System.getProperties().putIfAbsent("glass.gtk.uiScale", uiScale);
150-
}
151-
} else {
152-
LOG.warning("UI scale out of range: " + uiScale);
153-
}
154-
} catch (Throwable e) {
155-
LOG.warning("Invalid UI scale: " + uiScale);
156-
}
157-
}
158-
}
159-
16075
private static void createHMCLDirectories() {
16176
if (!Files.isDirectory(Metadata.HMCL_LOCAL_HOME)) {
16277
try {
@@ -284,60 +199,7 @@ private static void enableUnsafeMemoryAccess() {
284199
}
285200
}
286201

287-
private static void checkConfigOwner() {
288-
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS)
289-
return;
290-
291-
String userName = System.getProperty("user.name");
292-
Path configDirectory = SettingsManager.localConfigDirectory();
293-
if (!Files.exists(configDirectory)) {
294-
return;
295-
}
296-
297-
String owner;
298-
try {
299-
owner = Files.getOwner(configDirectory).getName();
300-
} catch (IOException ioe) {
301-
LOG.warning("Failed to get file owner", ioe);
302-
return;
303-
}
304-
305-
if (Files.isWritable(configDirectory) || userName.equals("root") || userName.equals(owner))
306-
return;
307-
308-
ArrayList<String> files = new ArrayList<>();
309-
files.add(configDirectory.toString());
310-
if (Files.exists(Metadata.HMCL_USER_HOME))
311-
files.add(Metadata.HMCL_USER_HOME.toString());
312-
313-
Path mcDir = Paths.get(".minecraft").toAbsolutePath().normalize();
314-
if (Files.exists(mcDir))
315-
files.add(mcDir.toString());
316-
317-
String command = new CommandBuilder().addAll("sudo", "chown", "-R", userName).addAll(files).toString();
318-
SwingUtils.initLookAndFeel();
319-
320-
Object[] options = {i18n("button.copy_and_exit"), i18n("button.cancel")};
321-
int result = JOptionPane.showOptionDialog(null,
322-
i18n("fatal.config_loading_failure.unix", owner, command),
323-
i18n("message.error"),
324-
JOptionPane.DEFAULT_OPTION,
325-
JOptionPane.ERROR_MESSAGE,
326-
null,
327-
options,
328-
options[0]);
329-
330-
if (result == 0) {
331-
try {
332-
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(command), null);
333-
} catch (Throwable e) {
334-
LOG.warning("Failed to copy command to clipboard", e);
335-
}
336-
}
337-
EntryPoint.exit(1);
338-
}
339-
340-
private static void showWarning(String message) {
202+
static void showWarning(String message) {
341203
SwingUtils.initLookAndFeel();
342204

343205
int result = JOptionPane.showOptionDialog(null, message, i18n("message.warning"), JOptionPane.OK_CANCEL_OPTION,
@@ -351,7 +213,7 @@ private static void showWarning(String message) {
351213
/**
352214
* Indicates that a fatal error has occurred, and that the application cannot start.
353215
*/
354-
private static void showErrorAndExit(String message) {
216+
static void showErrorAndExit(String message) {
355217
SwingUtils.showErrorDialog(message);
356218
exit(1);
357219
}

HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,20 @@
4747
import org.jackhuang.hmcl.util.io.JarUtils;
4848
import org.jackhuang.hmcl.util.platform.*;
4949

50+
import javax.swing.*;
51+
import java.awt.*;
52+
import java.awt.datatransfer.StringSelection;
5053
import java.io.File;
54+
import java.io.IOException;
5155
import java.lang.management.ManagementFactory;
5256
import java.lang.management.MemoryPoolMXBean;
5357
import java.net.CookieHandler;
5458
import java.net.CookieManager;
59+
import java.nio.file.Files;
60+
import java.nio.file.Path;
61+
import java.nio.file.Paths;
5562
import java.text.DecimalFormat;
63+
import java.util.ArrayList;
5664
import java.util.Objects;
5765
import java.util.Optional;
5866
import java.util.concurrent.TimeUnit;
@@ -315,6 +323,19 @@ public static void main(String[] args) {
315323

316324
Lang.thread(SystemInfo::initialize, "Detection System Information", true);
317325

326+
try {
327+
SettingsManager.init();
328+
} catch (SambaException e) {
329+
EntryPoint.showWarning(i18n("fatal.samba"));
330+
} catch (IOException e) {
331+
LOG.error("Failed to load config", e);
332+
checkConfigOwner();
333+
SwingUtils.showErrorDialog(i18n("fatal.config_loading_failure", SettingsManager.localConfigDirectory()));
334+
EntryPoint.exit(1);
335+
}
336+
337+
setupJavaFXVMOptions();
338+
318339
launch(Launcher.class, args);
319340
} catch (Throwable e) { // Fucking JavaFX will suppress the exception and will break our crash reporter.
320341
CRASH_REPORTER.uncaughtException(Thread.currentThread(), e);
@@ -347,5 +368,127 @@ public static void stopWithoutPlatform() {
347368
});
348369
}
349370

371+
private static void setupJavaFXVMOptions() {
372+
if ("true".equalsIgnoreCase(System.getenv("HMCL_FORCE_GPU"))) {
373+
LOG.info("HMCL_FORCE_GPU: true");
374+
System.getProperties().putIfAbsent("prism.forceGPU", "true");
375+
}
376+
377+
setUpAnimationFrameRate:
378+
{
379+
String animationFrameRate = System.getenv("HMCL_ANIMATION_FRAME_RATE");
380+
if (animationFrameRate != null) {
381+
LOG.info("HMCL_ANIMATION_FRAME_RATE: " + animationFrameRate);
382+
383+
try {
384+
if (Integer.parseInt(animationFrameRate) <= 0)
385+
throw new NumberFormatException(animationFrameRate);
386+
387+
System.getProperties().putIfAbsent("javafx.animation.pulse", animationFrameRate);
388+
} catch (NumberFormatException e) {
389+
LOG.warning("Invalid animation frame rate: " + animationFrameRate);
390+
}
391+
break setUpAnimationFrameRate;
392+
}
393+
}
394+
395+
String uiScale = System.getProperty("hmcl.uiScale", System.getenv("HMCL_UI_SCALE"));
396+
if (uiScale != null) {
397+
uiScale = uiScale.trim();
398+
399+
LOG.info("HMCL_UI_SCALE: " + uiScale);
400+
401+
try {
402+
float scaleValue;
403+
if (uiScale.endsWith("%")) {
404+
scaleValue = Integer.parseInt(uiScale.substring(0, uiScale.length() - 1)) / 100.0f;
405+
} else if (uiScale.endsWith("dpi") || uiScale.endsWith("DPI")) {
406+
scaleValue = Integer.parseInt(uiScale.substring(0, uiScale.length() - 3)) / 96.0f;
407+
} else {
408+
scaleValue = Float.parseFloat(uiScale);
409+
}
410+
411+
float lowerBound;
412+
float upperBound;
413+
414+
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) {
415+
// JavaFX behavior may be abnormal when the DPI scaling factor is too high
416+
lowerBound = 0.25f;
417+
upperBound = 4f;
418+
} else {
419+
lowerBound = 0.01f;
420+
upperBound = 10f;
421+
}
422+
423+
if (scaleValue >= lowerBound && scaleValue <= upperBound) {
424+
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) {
425+
System.getProperties().putIfAbsent("glass.win.uiScale", uiScale);
426+
} else if (OperatingSystem.CURRENT_OS == OperatingSystem.MACOS) {
427+
LOG.warning("macOS does not support setting UI scale, so it will be ignored");
428+
} else {
429+
System.getProperties().putIfAbsent("glass.gtk.uiScale", uiScale);
430+
}
431+
} else {
432+
LOG.warning("UI scale out of range: " + uiScale);
433+
}
434+
} catch (Throwable e) {
435+
LOG.warning("Invalid UI scale: " + uiScale);
436+
}
437+
}
438+
}
439+
440+
private static void checkConfigOwner() {
441+
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS)
442+
return;
443+
444+
String userName = System.getProperty("user.name");
445+
Path configDirectory = SettingsManager.localConfigDirectory();
446+
if (!Files.exists(configDirectory)) {
447+
return;
448+
}
449+
450+
String owner;
451+
try {
452+
owner = Files.getOwner(configDirectory).getName();
453+
} catch (IOException ioe) {
454+
LOG.warning("Failed to get file owner", ioe);
455+
return;
456+
}
457+
458+
if (Files.isWritable(configDirectory) || userName.equals("root") || userName.equals(owner))
459+
return;
460+
461+
ArrayList<String> files = new ArrayList<>();
462+
files.add(configDirectory.toString());
463+
if (Files.exists(Metadata.HMCL_USER_HOME))
464+
files.add(Metadata.HMCL_USER_HOME.toString());
465+
466+
Path mcDir = Paths.get(".minecraft").toAbsolutePath().normalize();
467+
if (Files.exists(mcDir))
468+
files.add(mcDir.toString());
469+
470+
String command = new CommandBuilder().addAll("sudo", "chown", "-R", userName).addAll(files).toString();
471+
SwingUtils.initLookAndFeel();
472+
473+
Object[] options = {i18n("button.copy_and_exit"), i18n("button.cancel")};
474+
int result = JOptionPane.showOptionDialog(null,
475+
i18n("fatal.config_loading_failure.unix", owner, command),
476+
i18n("message.error"),
477+
JOptionPane.DEFAULT_OPTION,
478+
JOptionPane.ERROR_MESSAGE,
479+
null,
480+
options,
481+
options[0]);
482+
483+
if (result == 0) {
484+
try {
485+
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(command), null);
486+
} catch (Throwable e) {
487+
LOG.warning("Failed to copy command to clipboard", e);
488+
}
489+
}
490+
EntryPoint.exit(1);
491+
}
492+
350493
public static final CrashReporter CRASH_REPORTER = new CrashReporter(true);
351494
}

HMCL/src/main/java/org/jackhuang/hmcl/setting/GameDirectory.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@
3434
import java.lang.reflect.Type;
3535
import java.util.Objects;
3636

37-
import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating;
38-
3937
/// Persistent configuration for a game directory.
4038
@JsonAdapter(GameDirectory.Serializer.class)
4139
@NotNullByDefault
@@ -118,7 +116,7 @@ public GameDirectory(
118116
this.path = new SimpleObjectProperty<>(this, "path", Objects.requireNonNull(path));
119117
this.legacyGameSettings = new SimpleObjectProperty<>(this, "legacyGameSettings", legacyGameSettings);
120118

121-
addPropertyChangedListener(onInvalidating(this::invalidate));
119+
addPropertyChangedListener(arg -> invalidate());
122120
}
123121

124122
/// Returns a debug string containing the game directory path and display metadata.

0 commit comments

Comments
 (0)