Fix stage GC

This commit is contained in:
crschnick
2025-10-31 21:57:45 +00:00
parent 627899979e
commit f72925d279
3 changed files with 77 additions and 35 deletions
@@ -22,7 +22,7 @@ public class AppStyle {
private static final Map<Path, String> STYLESHEET_CONTENTS = new LinkedHashMap<>();
private static final Map<AppTheme.Theme, String> THEME_SPECIFIC_STYLESHEET_CONTENTS = new LinkedHashMap<>();
private static final Map<AppTheme.Theme, String> THEME_PREFERENCES_STYLESHEET_CONTENTS = new LinkedHashMap<>();
private static final List<Scene> scenes = new ArrayList<>();
private static final WeakHashMap<Scene, Object> scenes = new WeakHashMap<>();
private static String FONT_CONTENTS = null;
public static void init() {
@@ -113,11 +113,11 @@ public class AppStyle {
private static void changeFontUsage(boolean use) {
if (!use) {
scenes.forEach(scene -> {
scenes.keySet().forEach(scene -> {
add(scene, FONT_CONTENTS);
});
} else {
scenes.forEach(scene -> {
scenes.keySet().forEach(scene -> {
scene.getStylesheets().remove(FONT_CONTENTS);
});
}
@@ -133,7 +133,7 @@ public class AppStyle {
return;
}
scenes.forEach(scene -> {
scenes.keySet().forEach(scene -> {
scene.getStylesheets().remove(THEME_PREFERENCES_STYLESHEET_CONTENTS.get(t));
});
THEME_PREFERENCES_STYLESHEET_CONTENTS.clear();
@@ -141,13 +141,13 @@ public class AppStyle {
THEME_PREFERENCES_STYLESHEET_CONTENTS.put(
theme, Styles.toDataURI(theme.getPlatformPreferencesStylesheet()));
}
scenes.forEach(scene -> {
scenes.keySet().forEach(scene -> {
add(scene, THEME_PREFERENCES_STYLESHEET_CONTENTS.get(t));
});
}
private static void changeTheme(AppTheme.Theme theme) {
scenes.forEach(scene -> {
scenes.keySet().forEach(scene -> {
scene.getStylesheets().removeAll(THEME_SPECIFIC_STYLESHEET_CONTENTS.values());
scene.getStylesheets().removeAll(THEME_PREFERENCES_STYLESHEET_CONTENTS.values());
add(scene, THEME_SPECIFIC_STYLESHEET_CONTENTS.get(theme));
@@ -183,6 +183,6 @@ public class AppStyle {
}
TrackEvent.debug("Added stylesheets for scene");
scenes.add(scene);
scenes.put(scene, null);
}
}
@@ -32,6 +32,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.SneakyThrows;
import java.lang.ref.WeakReference;
import java.nio.file.Files;
import java.util.List;
import java.util.function.Supplier;
@@ -46,41 +47,65 @@ public class AppTheme {
private static boolean init;
public static void initThemeHandlers(Stage stage) {
stage.getScene().rootProperty().subscribe(root -> {
if (root == null) {
return;
}
if (stage.getScene() == null) {
return;
}
var root = stage.getScene().getRoot();
if (root != null) {
root.pseudoClassStateChanged(
PseudoClass.getPseudoClass(OsType.ofLocal().getId()), true);
if (AppPrefs.get() == null) {
}
if (AppPrefs.get() == null) {
if (root != null) {
var def = Theme.getDefaultLightTheme();
root.pseudoClassStateChanged(PseudoClass.getPseudoClass(def.getCssId()), true);
root.pseudoClassStateChanged(LIGHT, true);
root.pseudoClassStateChanged(DARK, false);
root.pseudoClassStateChanged(PRETTY, true);
root.pseudoClassStateChanged(PERFORMANCE, false);
return;
}
return;
}
AppPrefs.get().theme().subscribe(t -> {
Theme.ALL.forEach(theme -> {
root.pseudoClassStateChanged(
PseudoClass.getPseudoClass(theme.getCssId()),
theme.getCssId().equals(t.getCssId()));
});
if (t == null) {
return;
// Allow for GC
var ref = new WeakReference<>(stage);
AppPrefs.get().theme().subscribe(t -> {
var val = ref.get();
if (val != null) {
var scene = val.getScene();
if (scene != null) {
var r = scene.getRoot();
if (r != null) {
Theme.ALL.forEach(theme -> {
r.pseudoClassStateChanged(
PseudoClass.getPseudoClass(theme.getCssId()),
theme.getCssId().equals(t.getCssId()));
});
if (t != null) {
r.pseudoClassStateChanged(LIGHT, !t.isDark());
r.pseudoClassStateChanged(DARK, t.isDark());
}
}
}
}
});
root.pseudoClassStateChanged(LIGHT, !t.isDark());
root.pseudoClassStateChanged(DARK, t.isDark());
});
AppPrefs.get().performanceMode().subscribe(val -> {
root.pseudoClassStateChanged(PRETTY, !val);
root.pseudoClassStateChanged(PERFORMANCE, val);
});
AppPrefs.get().performanceMode().subscribe(pm -> {
var val = ref.get();
if (val != null) {
var scene = val.getScene();
if (scene != null) {
var r = scene.getRoot();
if (r != null) {
r.pseudoClassStateChanged(PRETTY, !pm);
r.pseudoClassStateChanged(PERFORMANCE, pm);
}
}
}
});
}
@@ -20,6 +20,8 @@ import javafx.util.Duration;
import lombok.SneakyThrows;
import org.apache.commons.lang3.SystemUtils;
import java.lang.ref.WeakReference;
public class AppModifiedStage extends Stage {
public static boolean mergeFrame() {
@@ -30,9 +32,11 @@ public class AppModifiedStage extends Stage {
ObservableList<Window> list = Window.getWindows();
list.addListener((ListChangeListener<Window>) c -> {
if (c.next() && c.wasAdded()) {
var added = c.getAddedSubList().getFirst();
if (added instanceof Stage stage) {
hookUpStage(stage);
var added = c.getAddedSubList();
for (Window window : added) {
if (window instanceof Stage stage) {
hookUpStage(stage);
}
}
}
});
@@ -46,17 +50,30 @@ public class AppModifiedStage extends Stage {
private static void hookUpStage(Stage stage) {
applyModes(stage);
// Fix GC not working when the stage is no longer needed
var ref = new WeakReference<>(stage);
if (AppPrefs.get() != null) {
AppPrefs.get().theme().addListener((observable, oldValue, newValue) -> {
updateStage(stage);
var val = ref.get();
if (val != null) {
updateStage(val);
}
});
AppPrefs.get().performanceMode().addListener((observable, oldValue, newValue) -> {
updateStage(stage);
var val = ref.get();
if (val != null) {
updateStage(val);
}
});
}
if (stage.getScene() != null) {
stage.getScene().rootProperty().addListener((observable, oldValue, newValue) -> {
applyModes(stage);
var val = ref.get();
if (val != null) {
applyModes(val);
}
});
}
}