Skip to content

Commit 179ccb7

Browse files
authored
在 Windows 平台上 GameCrashWindow 标题栏应当跟随深色模式设置 (#5319)
1 parent f7987a9 commit 179ccb7

3 files changed

Lines changed: 49 additions & 40 deletions

File tree

HMCL/src/main/java/org/jackhuang/hmcl/theme/Themes.java

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,36 @@
1717
*/
1818
package org.jackhuang.hmcl.theme;
1919

20+
import com.sun.jna.Pointer;
2021
import javafx.beans.Observable;
2122
import javafx.beans.binding.Bindings;
2223
import javafx.beans.binding.BooleanBinding;
2324
import javafx.beans.binding.ObjectBinding;
2425
import javafx.beans.binding.ObjectExpression;
2526
import javafx.beans.value.ChangeListener;
2627
import javafx.beans.value.ObservableValue;
28+
import javafx.event.EventHandler;
2729
import javafx.scene.paint.Color;
30+
import javafx.stage.Stage;
31+
import javafx.stage.WindowEvent;
2832
import org.glavo.monetfx.Brightness;
2933
import org.glavo.monetfx.ColorScheme;
3034
import org.glavo.monetfx.Contrast;
3135
import org.glavo.monetfx.beans.property.ColorSchemeProperty;
3236
import org.glavo.monetfx.beans.property.ReadOnlyColorSchemeProperty;
3337
import org.glavo.monetfx.beans.property.SimpleColorSchemeProperty;
3438
import org.jackhuang.hmcl.ui.FXUtils;
39+
import org.jackhuang.hmcl.ui.WindowsNativeUtils;
40+
import org.jackhuang.hmcl.util.platform.NativeUtils;
41+
import org.jackhuang.hmcl.util.platform.OSVersion;
3542
import org.jackhuang.hmcl.util.platform.OperatingSystem;
3643
import org.jackhuang.hmcl.util.platform.SystemUtils;
44+
import org.jackhuang.hmcl.util.platform.windows.Dwmapi;
45+
import org.jackhuang.hmcl.util.platform.windows.WinConstants;
3746
import org.jackhuang.hmcl.util.platform.windows.WinReg;
47+
import org.jackhuang.hmcl.util.platform.windows.WinTypes;
3848

39-
import java.util.ArrayList;
40-
import java.util.List;
41-
import java.util.Locale;
42-
import java.util.Objects;
49+
import java.util.*;
4350

4451
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
4552

@@ -160,6 +167,39 @@ public static BooleanBinding darkModeProperty() {
160167
return darkMode;
161168
}
162169

170+
public static void applyNativeDarkMode(Stage stage) {
171+
if (OperatingSystem.SYSTEM_VERSION.isAtLeast(OSVersion.WINDOWS_11) && NativeUtils.USE_JNA && Dwmapi.INSTANCE != null) {
172+
ChangeListener<Boolean> listener = FXUtils.onWeakChange(Themes.darkModeProperty(), darkMode -> {
173+
if (stage.isShowing()) {
174+
WindowsNativeUtils.getWindowHandle(stage).ifPresent(handle -> {
175+
if (handle == WinTypes.HANDLE.INVALID_VALUE)
176+
return;
177+
178+
Dwmapi.INSTANCE.DwmSetWindowAttribute(
179+
new WinTypes.HANDLE(Pointer.createConstant(handle)),
180+
WinConstants.DWMWA_USE_IMMERSIVE_DARK_MODE,
181+
new WinTypes.BOOLByReference(new WinTypes.BOOL(darkMode)),
182+
WinTypes.BOOL.SIZE
183+
);
184+
});
185+
}
186+
});
187+
stage.getProperties().put("Themes.applyNativeDarkMode.listener", listener);
188+
189+
if (stage.isShowing()) {
190+
listener.changed(null, false, Themes.darkModeProperty().get());
191+
} else {
192+
stage.addEventFilter(WindowEvent.WINDOW_SHOWN, new EventHandler<>() {
193+
@Override
194+
public void handle(WindowEvent event) {
195+
stage.removeEventFilter(WindowEvent.WINDOW_SHOWN, this);
196+
listener.changed(null, false, Themes.darkModeProperty().get());
197+
}
198+
});
199+
}
200+
}
201+
}
202+
163203
private Themes() {
164204
}
165205
}

HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.jackhuang.hmcl.setting.StyleSheets;
4141
import org.jackhuang.hmcl.task.Schedulers;
4242
import org.jackhuang.hmcl.task.Task;
43+
import org.jackhuang.hmcl.theme.Themes;
4344
import org.jackhuang.hmcl.ui.construct.MessageDialogPane;
4445
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
4546
import org.jackhuang.hmcl.util.Lang;
@@ -90,6 +91,8 @@ public class GameCrashWindow extends Stage {
9091
private final List<Log> logs;
9192

9293
public GameCrashWindow(ManagedProcess managedProcess, ProcessListener.ExitType exitType, DefaultGameRepository repository, Version version, LaunchOptions launchOptions, List<Log> logs) {
94+
Themes.applyNativeDarkMode(this);
95+
9396
this.managedProcess = managedProcess;
9497
this.exitType = exitType;
9598
this.repository = repository;

HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,13 @@
2121
import com.jfoenix.controls.JFXCheckBox;
2222
import com.jfoenix.controls.JFXComboBox;
2323
import com.jfoenix.controls.JFXListView;
24-
import com.sun.jna.Pointer;
2524
import javafx.application.Platform;
2625
import javafx.beans.InvalidationListener;
2726
import javafx.beans.binding.Bindings;
2827
import javafx.beans.property.*;
2928
import javafx.collections.FXCollections;
3029
import javafx.collections.ObservableList;
3130
import javafx.css.PseudoClass;
32-
import javafx.event.EventHandler;
3331
import javafx.geometry.Insets;
3432
import javafx.geometry.Pos;
3533
import javafx.scene.Scene;
@@ -38,7 +36,6 @@
3836
import javafx.scene.input.MouseButton;
3937
import javafx.scene.layout.*;
4038
import javafx.stage.Stage;
41-
import javafx.stage.WindowEvent;
4239
import org.jackhuang.hmcl.game.GameDumpGenerator;
4340
import org.jackhuang.hmcl.game.Log;
4441
import org.jackhuang.hmcl.setting.StyleSheets;
@@ -48,9 +45,6 @@
4845
import org.jackhuang.hmcl.ui.construct.SpinnerPane;
4946
import org.jackhuang.hmcl.util.*;
5047
import org.jackhuang.hmcl.util.platform.*;
51-
import org.jackhuang.hmcl.util.platform.windows.Dwmapi;
52-
import org.jackhuang.hmcl.util.platform.windows.WinConstants;
53-
import org.jackhuang.hmcl.util.platform.windows.WinTypes;
5448

5549
import java.io.IOException;
5650
import java.nio.file.Files;
@@ -87,41 +81,13 @@ public final class LogWindow extends Stage {
8781
private final LogWindowImpl impl;
8882
private final ManagedProcess gameProcess;
8983

90-
@SuppressWarnings("unused")
91-
private Object windowsDarkModeListenerHolder;
92-
93-
{
94-
if (OperatingSystem.SYSTEM_VERSION.isAtLeast(OSVersion.WINDOWS_11) && NativeUtils.USE_JNA && Dwmapi.INSTANCE != null) {
95-
this.addEventFilter(WindowEvent.WINDOW_SHOWN, new EventHandler<>() {
96-
@Override
97-
public void handle(WindowEvent event) {
98-
LogWindow.this.removeEventFilter(WindowEvent.WINDOW_SHOWN, this);
99-
100-
windowsDarkModeListenerHolder = FXUtils.onWeakChangeAndOperate(Themes.darkModeProperty(), darkMode -> {
101-
if (LogWindow.this.isShowing()) {
102-
WindowsNativeUtils.getWindowHandle(LogWindow.this).ifPresent(handle -> {
103-
if (handle == WinTypes.HANDLE.INVALID_VALUE)
104-
return;
105-
106-
Dwmapi.INSTANCE.DwmSetWindowAttribute(
107-
new WinTypes.HANDLE(Pointer.createConstant(handle)),
108-
WinConstants.DWMWA_USE_IMMERSIVE_DARK_MODE,
109-
new WinTypes.BOOLByReference(new WinTypes.BOOL(darkMode)),
110-
WinTypes.BOOL.SIZE
111-
);
112-
});
113-
}
114-
});
115-
}
116-
});
117-
}
118-
}
119-
12084
public LogWindow(ManagedProcess gameProcess) {
12185
this(gameProcess, new CircularArrayList<>());
12286
}
12387

12488
public LogWindow(ManagedProcess gameProcess, CircularArrayList<Log> logs) {
89+
Themes.applyNativeDarkMode(this);
90+
12591
this.logs = logs;
12692
this.impl = new LogWindowImpl();
12793
setScene(new Scene(impl, 800, 480));

0 commit comments

Comments
 (0)