mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-22 07:30:24 +00:00
Merge branch native-window into master
This commit is contained in:
parent
914f724577
commit
4d43cc5fd0
44 changed files with 290 additions and 124 deletions
|
@ -3,7 +3,7 @@ package io.xpipe.app.browser;
|
|||
import io.xpipe.app.browser.file.BrowserEntry;
|
||||
import io.xpipe.app.comp.base.ListBoxViewComp;
|
||||
import io.xpipe.app.core.AppStyle;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.fxcomps.SimpleComp;
|
||||
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.xpipe.app.browser.file;
|
||||
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.core.store.FileKind;
|
||||
import io.xpipe.core.store.FileSystem;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import io.xpipe.app.comp.store.StoreEntryWrapper;
|
|||
import io.xpipe.app.core.AppFont;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppLayoutModel;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.fxcomps.SimpleComp;
|
||||
import io.xpipe.app.fxcomps.util.BindingsHelper;
|
||||
|
|
|
@ -34,13 +34,13 @@ public class AppLayoutComp extends Comp<CompStructure<Pane>> {
|
|||
},
|
||||
model.getSelected())));
|
||||
var multi = new MultiContentComp(map);
|
||||
multi.styleClass("background");
|
||||
|
||||
var pane = new BorderPane();
|
||||
var sidebar = new SideMenuBarComp(model.getSelected(), model.getEntries());
|
||||
StackPane multiR = (StackPane) multi.createRegion();
|
||||
pane.setCenter(multiR);
|
||||
pane.setRight(sidebar.createRegion());
|
||||
pane.getStyleClass().add("background");
|
||||
model.getSelected().addListener((c, o, n) -> {
|
||||
if (o != null && o.equals(model.getEntries().get(2))) {
|
||||
AppPrefs.get().save();
|
||||
|
@ -48,6 +48,7 @@ public class AppLayoutComp extends Comp<CompStructure<Pane>> {
|
|||
}
|
||||
});
|
||||
AppFont.normal(pane);
|
||||
pane.getStyleClass().add("layout");
|
||||
return new SimpleCompStructure<>(pane);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.xpipe.app.comp.base;
|
||||
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.fxcomps.CompStructure;
|
||||
import io.xpipe.app.fxcomps.SimpleCompStructure;
|
||||
|
|
|
@ -196,7 +196,6 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
|
|||
vbox.getChildren().add(filler);
|
||||
VBox.setVgrow(filler, Priority.ALWAYS);
|
||||
filler.prefWidthProperty().bind(((Region) vbox.getChildren().getFirst()).widthProperty());
|
||||
|
||||
vbox.getStyleClass().add("sidebar-comp");
|
||||
return new SimpleCompStructure<>(vbox);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import io.xpipe.app.comp.base.DialogComp;
|
|||
import io.xpipe.app.comp.base.ErrorOverlayComp;
|
||||
import io.xpipe.app.comp.base.PopupMenuButtonComp;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.ext.DataStoreProvider;
|
||||
import io.xpipe.app.ext.DataStoreProviders;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
package io.xpipe.app.core;
|
||||
|
||||
import io.xpipe.app.comp.AppLayoutComp;
|
||||
import io.xpipe.app.core.window.AppMainWindow;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||
import io.xpipe.app.issue.TrackEvent;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.app.update.XPipeDistributionType;
|
||||
import io.xpipe.app.util.LicenseProvider;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.xpipe.app.core;
|
||||
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.launcher.LauncherInput;
|
||||
|
||||
import javafx.scene.control.Alert;
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.xpipe.app.core;
|
|||
|
||||
import io.xpipe.app.comp.base.MarkdownComp;
|
||||
import io.xpipe.app.core.mode.OperationMode;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.xpipe.app.core;
|
||||
|
||||
import io.xpipe.app.comp.base.ModalOverlayComp;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.ext.PrefsChoiceValue;
|
||||
import io.xpipe.app.fxcomps.impl.TooltipAugment;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
|
|
|
@ -1,29 +1,28 @@
|
|||
package io.xpipe.app.core;
|
||||
|
||||
import atlantafx.base.theme.*;
|
||||
import io.xpipe.app.core.window.AppMainWindow;
|
||||
import io.xpipe.app.ext.PrefsChoiceValue;
|
||||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.issue.TrackEvent;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.core.process.OsType;
|
||||
|
||||
import javafx.animation.*;
|
||||
import javafx.animation.Interpolator;
|
||||
import javafx.animation.KeyFrame;
|
||||
import javafx.animation.KeyValue;
|
||||
import javafx.animation.Timeline;
|
||||
import javafx.application.Application;
|
||||
import javafx.application.ColorScheme;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.css.PseudoClass;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.Window;
|
||||
import javafx.stage.WindowEvent;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import atlantafx.base.theme.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
|
@ -45,8 +44,6 @@ public class AppTheme {
|
|||
return;
|
||||
}
|
||||
|
||||
initWindowsThemeHandler(stage);
|
||||
|
||||
Runnable r = () -> {
|
||||
AppPrefs.get().theme.subscribe(t -> {
|
||||
Theme.ALL.forEach(
|
||||
|
@ -74,46 +71,6 @@ public class AppTheme {
|
|||
}
|
||||
}
|
||||
|
||||
private static void initWindowsThemeHandler(Window stage) {
|
||||
if (OsType.getLocal() != OsType.WINDOWS) {
|
||||
return;
|
||||
}
|
||||
|
||||
EventHandler<WindowEvent> windowTheme = new EventHandler<>() {
|
||||
@Override
|
||||
public void handle(WindowEvent event) {
|
||||
if (!stage.isShowing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// var c = new WindowControl(stage);
|
||||
// c.setWindowAttribute(20, AppPrefs.get().theme.getValue().isDark());
|
||||
// c.setWindowAttribute(34, 0xFFFFFFFEL);
|
||||
// c.redraw();
|
||||
} catch (Throwable e) {
|
||||
ErrorEvent.fromThrowable(e).handle();
|
||||
}
|
||||
stage.removeEventFilter(WindowEvent.WINDOW_SHOWN, this);
|
||||
}
|
||||
};
|
||||
if (stage.isShowing()) {
|
||||
windowTheme.handle(null);
|
||||
} else {
|
||||
stage.addEventFilter(WindowEvent.WINDOW_SHOWN, windowTheme);
|
||||
}
|
||||
|
||||
AppPrefs.get().theme.addListener((observable, oldValue, newValue) -> {
|
||||
Platform.runLater(() -> {
|
||||
var transition = new PauseTransition(Duration.millis(300));
|
||||
transition.setOnFinished(e -> {
|
||||
windowTheme.handle(null);
|
||||
});
|
||||
transition.play();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
if (init) {
|
||||
return;
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.xpipe.app.core.check;
|
|||
import io.xpipe.app.comp.base.MarkdownComp;
|
||||
import io.xpipe.app.core.*;
|
||||
import io.xpipe.app.core.mode.OperationMode;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.util.PlatformState;
|
||||
import io.xpipe.app.util.WindowsRegistry;
|
||||
import io.xpipe.core.process.OsType;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.xpipe.app.core.check;
|
||||
|
||||
import io.xpipe.app.core.AppProperties;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
|
||||
import javafx.scene.control.Alert;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import io.xpipe.app.browser.file.LocalFileSystem;
|
|||
import io.xpipe.app.browser.icon.FileIconManager;
|
||||
import io.xpipe.app.core.App;
|
||||
import io.xpipe.app.core.AppGreetings;
|
||||
import io.xpipe.app.core.AppMainWindow;
|
||||
import io.xpipe.app.core.window.AppMainWindow;
|
||||
import io.xpipe.app.core.check.AppPtbCheck;
|
||||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
|
|
|
@ -3,6 +3,7 @@ package io.xpipe.app.core.mode;
|
|||
import io.xpipe.app.comp.store.StoreViewState;
|
||||
import io.xpipe.app.core.*;
|
||||
import io.xpipe.app.core.check.AppFontLoadingCheck;
|
||||
import io.xpipe.app.core.window.ModifiedStage;
|
||||
import io.xpipe.app.issue.TrackEvent;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.app.update.UpdateAvailableAlert;
|
||||
|
@ -34,6 +35,7 @@ public abstract class PlatformMode extends OperationMode {
|
|||
AppStyle.init();
|
||||
AppImages.init();
|
||||
AppLayoutModel.init();
|
||||
ModifiedStage.init();
|
||||
TrackEvent.info("Finished essential component initialization before platform");
|
||||
|
||||
TrackEvent.info("Launching application ...");
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package io.xpipe.app.core;
|
||||
package io.xpipe.app.core.window;
|
||||
|
||||
import io.xpipe.app.core.AppCache;
|
||||
import io.xpipe.app.core.AppImages;
|
||||
import io.xpipe.app.core.AppProperties;
|
||||
import io.xpipe.app.core.AppTheme;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.issue.TrackEvent;
|
||||
|
@ -7,7 +11,6 @@ import io.xpipe.app.prefs.AppPrefs;
|
|||
import io.xpipe.app.prefs.CloseBehaviourAlert;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
import io.xpipe.core.process.OsType;
|
||||
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.geometry.Rectangle2D;
|
||||
|
@ -15,20 +18,21 @@ import javafx.scene.Scene;
|
|||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.stage.Screen;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import javafx.stage.StageStyle;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Value;
|
||||
import lombok.extern.jackson.Jacksonized;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
public class AppMainWindow {
|
||||
|
||||
|
@ -48,6 +52,8 @@ public class AppMainWindow {
|
|||
public static AppMainWindow init(Stage stage) {
|
||||
INSTANCE = new AppMainWindow(stage);
|
||||
var scene = new Scene(new Region(), -1, -1, false);
|
||||
scene.setFill(Color.TRANSPARENT);
|
||||
stage.initStyle(StageStyle.UNIFIED);
|
||||
stage.setScene(scene);
|
||||
AppWindowHelper.setupStylesheets(stage.getScene());
|
||||
return INSTANCE;
|
||||
|
@ -256,7 +262,6 @@ public class AppMainWindow {
|
|||
|
||||
private void setupContent(Comp<?> content) {
|
||||
var contentR = content.createRegion();
|
||||
contentR.requestFocus();
|
||||
stage.getScene().setRoot(contentR);
|
||||
AppTheme.initThemeHandlers(stage);
|
||||
TrackEvent.debug("Set content scene");
|
|
@ -1,6 +1,7 @@
|
|||
package io.xpipe.app.core;
|
||||
package io.xpipe.app.core.window;
|
||||
|
||||
import io.xpipe.app.comp.base.LoadingOverlayComp;
|
||||
import io.xpipe.app.core.*;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.issue.TrackEvent;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
|
@ -0,0 +1,16 @@
|
|||
package io.xpipe.app.core.window;
|
||||
|
||||
public enum DmwaWindowAttribute {
|
||||
DWMWA_USE_IMMERSIVE_DARK_MODE(20),
|
||||
DWMWA_SYSTEMBACKDROP_TYPE(38);
|
||||
|
||||
private final int value;
|
||||
|
||||
DmwaWindowAttribute(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int get() {
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package io.xpipe.app.core.window;
|
||||
|
||||
public enum DwmSystemBackDropType {
|
||||
NONE(1),
|
||||
MICA(2),
|
||||
MICA_ALT(4),
|
||||
ACRYLIC(3);
|
||||
|
||||
private final int value;
|
||||
|
||||
DwmSystemBackDropType(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int get() {
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package io.xpipe.app.core.window;
|
||||
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.Dialog;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.Window;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
public class ModifiedAlertStage {
|
||||
|
||||
@SneakyThrows
|
||||
public static void setForAlert(Alert alert) {
|
||||
var dialogClass = Dialog.class;
|
||||
var dialogField = dialogClass.getDeclaredField("dialog");
|
||||
dialogField.setAccessible(true);
|
||||
var dialog = (Dialog<?>) dialogField.get(alert);
|
||||
|
||||
var c = Class.forName("javafx.scene.control.HeavyweightDialog");
|
||||
var positionStageMethod = c.getDeclaredMethod("positionStage");
|
||||
positionStageMethod.setAccessible(true);
|
||||
|
||||
var stageField = c.getDeclaredField("stage");
|
||||
stageField.setAccessible(true);
|
||||
|
||||
var m = new Stage() {
|
||||
@SneakyThrows
|
||||
@Override public void centerOnScreen() {
|
||||
Window owner = getOwner();
|
||||
if (owner != null) {
|
||||
positionStageMethod.invoke(dialog);
|
||||
} else {
|
||||
if (getWidth() > 0 && getHeight() > 0) {
|
||||
super.centerOnScreen();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
stageField.set(alert,m);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package io.xpipe.app.core.window;
|
||||
|
||||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.core.process.OsType;
|
||||
import javafx.animation.PauseTransition;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.css.PseudoClass;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.Window;
|
||||
import javafx.util.Duration;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
public class ModifiedStage extends Stage {
|
||||
|
||||
@SneakyThrows
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void init() {
|
||||
var windowsField = Window.class.getDeclaredField("windows");
|
||||
windowsField.setAccessible(true);
|
||||
ObservableList<Window> list = (ObservableList<Window>) windowsField.get(null);
|
||||
list.addListener((ListChangeListener<Window>) c -> {
|
||||
if (c.next() && c.wasAdded()) {
|
||||
var added = c.getAddedSubList().getFirst();
|
||||
if (added instanceof Stage stage) {
|
||||
hookUpStage(stage);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void hookUpStage(Stage stage) {
|
||||
applyModes(stage);
|
||||
if (AppPrefs.get() != null) {
|
||||
AppPrefs.get().theme.addListener((observable, oldValue, newValue) -> {
|
||||
updateStage(stage);
|
||||
});
|
||||
AppPrefs.get().performanceMode().addListener((observable, oldValue, newValue) -> {
|
||||
updateStage(stage);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyModes(Stage stage) {
|
||||
if (OsType.getLocal() != OsType.WINDOWS || AppPrefs.get() == null) {
|
||||
stage.getScene().getRoot().pseudoClassStateChanged(PseudoClass.getPseudoClass("seamless-frame"), false);
|
||||
stage.getScene().getRoot().pseudoClassStateChanged(PseudoClass.getPseudoClass("separate-frame"), true);
|
||||
return;
|
||||
}
|
||||
|
||||
var ctrl = new NativeWinWindowControl(stage);
|
||||
ctrl.setWindowAttribute(DmwaWindowAttribute.DWMWA_USE_IMMERSIVE_DARK_MODE.get(), AppPrefs.get().theme.getValue().isDark());
|
||||
boolean backdrop;
|
||||
if (AppPrefs.get().performanceMode().get()) {
|
||||
backdrop = false;
|
||||
} else {
|
||||
backdrop = ctrl.setWindowBackdrop(DwmSystemBackDropType.MICA_ALT);
|
||||
}
|
||||
stage.getScene().getRoot().pseudoClassStateChanged(PseudoClass.getPseudoClass("seamless-frame"), backdrop);
|
||||
stage.getScene().getRoot().pseudoClassStateChanged(PseudoClass.getPseudoClass("separate-frame"), !backdrop);
|
||||
}
|
||||
|
||||
private static void updateStage(Stage stage) {
|
||||
if (!stage.isShowing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PlatformThread.runLaterIfNeeded(() -> {
|
||||
var transition = new PauseTransition(Duration.millis(300));
|
||||
transition.setOnFinished(e -> {
|
||||
applyModes(stage);
|
||||
stage.setWidth(stage.getWidth() - 1);
|
||||
Platform.runLater(() -> {
|
||||
stage.setWidth(stage.getWidth() + 1);
|
||||
});
|
||||
});
|
||||
transition.play();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,25 +1,25 @@
|
|||
package io.xpipe.app.util;
|
||||
|
||||
import javafx.stage.Window;
|
||||
package io.xpipe.app.core.window;
|
||||
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.PointerType;
|
||||
import com.sun.jna.platform.win32.User32;
|
||||
import com.sun.jna.platform.win32.WinDef;
|
||||
import com.sun.jna.platform.win32.WinNT;
|
||||
import javafx.stage.Window;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@Getter
|
||||
public class WindowControl {
|
||||
public class NativeWinWindowControl {
|
||||
|
||||
private final WinDef.HWND windowHandle;
|
||||
|
||||
public WindowControl(Window stage) throws Exception {
|
||||
Method tkStageGetter = stage.getClass().getSuperclass().getDeclaredMethod("getPeer");
|
||||
@SneakyThrows
|
||||
public NativeWinWindowControl(Window stage) {
|
||||
Method tkStageGetter = Window.class.getDeclaredMethod("getPeer");
|
||||
tkStageGetter.setAccessible(true);
|
||||
Object tkStage = tkStageGetter.invoke(stage);
|
||||
Method getPlatformWindow = tkStage.getClass().getDeclaredMethod("getPlatformWindow");
|
||||
|
@ -32,7 +32,7 @@ public class WindowControl {
|
|||
this.windowHandle = hwnd;
|
||||
}
|
||||
|
||||
public WindowControl(WinDef.HWND windowHandle) {
|
||||
public NativeWinWindowControl(WinDef.HWND windowHandle) {
|
||||
this.windowHandle = windowHandle;
|
||||
}
|
||||
|
||||
|
@ -40,27 +40,25 @@ public class WindowControl {
|
|||
User32.INSTANCE.SetWindowPos(windowHandle, new WinDef.HWND(), x, y, w, h, 0);
|
||||
}
|
||||
|
||||
public void setWindowAttribute(int attribute, boolean attributeValue) {
|
||||
DwmSupport.INSTANCE.DwmSetWindowAttribute(
|
||||
public boolean setWindowAttribute(int attribute, boolean attributeValue) {
|
||||
var r = Dwm.INSTANCE.DwmSetWindowAttribute(
|
||||
windowHandle, attribute, new WinDef.BOOLByReference(new WinDef.BOOL(attributeValue)), WinDef.BOOL.SIZE);
|
||||
return r.longValue() == 0;
|
||||
}
|
||||
|
||||
public void setWindowAttribute(int attribute, long attributeValue) {
|
||||
DwmSupport.INSTANCE.DwmSetWindowAttribute(
|
||||
public boolean setWindowBackdrop(DwmSystemBackDropType backdrop) {
|
||||
var r = Dwm.INSTANCE.DwmSetWindowAttribute(
|
||||
windowHandle,
|
||||
attribute,
|
||||
new WinDef.DWORDByReference(new WinDef.DWORD(attributeValue)),
|
||||
WinDef.DWORD.SIZE);
|
||||
DmwaWindowAttribute.DWMWA_SYSTEMBACKDROP_TYPE.get(),
|
||||
new WinDef.DWORDByReference(new WinDef.DWORD(backdrop.get())),
|
||||
WinDef.DWORD.SIZE
|
||||
);
|
||||
return r.longValue() == 0;
|
||||
}
|
||||
|
||||
public void redraw() {
|
||||
User32.INSTANCE.RedrawWindow(
|
||||
windowHandle, null, null, new WinDef.DWORD(User32.RDW_FRAME | User32.RDW_VALIDATE));
|
||||
}
|
||||
public interface Dwm extends Library {
|
||||
|
||||
public interface DwmSupport extends Library {
|
||||
|
||||
DwmSupport INSTANCE = Native.load("dwmapi", DwmSupport.class);
|
||||
Dwm INSTANCE = com.sun.jna.Native.load("dwmapi", Dwm.class);
|
||||
|
||||
WinNT.HRESULT DwmSetWindowAttribute(
|
||||
WinDef.HWND hwnd, int dwAttribute, PointerType pvAttribute, int cbAttribute);
|
|
@ -4,7 +4,7 @@ import io.xpipe.app.browser.session.BrowserChooserComp;
|
|||
import io.xpipe.app.comp.base.ButtonComp;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppLayoutModel;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.fxcomps.CompStructure;
|
||||
import io.xpipe.app.fxcomps.SimpleCompStructure;
|
||||
|
|
|
@ -93,8 +93,9 @@ public class PrettyImageComp extends SimpleComp {
|
|||
stack.getChildren().add(storeIcon);
|
||||
|
||||
Consumer<String> update = val -> {
|
||||
var useDark = AppPrefs.get() != null && AppPrefs.get().theme.get() != null && AppPrefs.get().theme.get().isDark();
|
||||
var fixed = val != null
|
||||
? FileNames.getBaseName(val) + (AppPrefs.get().theme.get().isDark() ? "-dark" : "") + "."
|
||||
? FileNames.getBaseName(val) + (useDark ? "-dark" : "") + "."
|
||||
+ FileNames.getExtension(val)
|
||||
: null;
|
||||
image.set(fixed);
|
||||
|
@ -107,9 +108,11 @@ public class PrettyImageComp extends SimpleComp {
|
|||
};
|
||||
|
||||
PlatformThread.sync(value).subscribe(update);
|
||||
AppPrefs.get().theme.addListener((observable, oldValue, newValue) -> {
|
||||
update.accept(value.getValue());
|
||||
});
|
||||
if (AppPrefs.get() != null) {
|
||||
AppPrefs.get().theme.addListener((observable, oldValue, newValue) -> {
|
||||
update.accept(value.getValue());
|
||||
});
|
||||
}
|
||||
|
||||
stack.setFocusTraversable(false);
|
||||
stack.setPrefWidth(width);
|
||||
|
|
|
@ -88,17 +88,20 @@ public class PrettySvgComp extends SimpleComp {
|
|||
}
|
||||
|
||||
Consumer<String> update = val -> {
|
||||
var useDark = AppPrefs.get() != null && AppPrefs.get().theme.get() != null && AppPrefs.get().theme.get().isDark();
|
||||
var fixed = val != null
|
||||
? FileNames.getBaseName(val) + (AppPrefs.get().theme.get().isDark() ? "-dark" : "") + "."
|
||||
? FileNames.getBaseName(val) + (useDark ? "-dark" : "") + "."
|
||||
+ FileNames.getExtension(val)
|
||||
: null;
|
||||
image.set(fixed);
|
||||
};
|
||||
|
||||
syncValue.subscribe(update);
|
||||
AppPrefs.get().theme.addListener((observable, oldValue, newValue) -> {
|
||||
update.accept(syncValue.getValue());
|
||||
});
|
||||
if (AppPrefs.get() != null) {
|
||||
AppPrefs.get().theme.addListener((observable, oldValue, newValue) -> {
|
||||
update.accept(syncValue.getValue());
|
||||
});
|
||||
}
|
||||
|
||||
stack.setFocusTraversable(false);
|
||||
stack.setPrefWidth(width);
|
||||
|
|
|
@ -5,7 +5,7 @@ import io.xpipe.app.comp.base.TitledPaneComp;
|
|||
import io.xpipe.app.core.AppFont;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppLayoutModel;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.fxcomps.SimpleComp;
|
||||
import io.xpipe.app.fxcomps.augment.GrowAugment;
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.xpipe.app.issue;
|
|||
|
||||
import io.xpipe.app.core.*;
|
||||
import io.xpipe.app.core.mode.OperationMode;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.update.XPipeDistributionType;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
import io.xpipe.app.util.ThreadHelper;
|
||||
|
|
|
@ -5,6 +5,7 @@ import io.xpipe.app.comp.base.ListSelectorComp;
|
|||
import io.xpipe.app.comp.base.MarkdownComp;
|
||||
import io.xpipe.app.comp.base.TitledPaneComp;
|
||||
import io.xpipe.app.core.*;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.fxcomps.SimpleComp;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package io.xpipe.app.prefs;
|
|||
import io.xpipe.app.comp.base.TileButtonComp;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppProperties;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.fxcomps.impl.LabelComp;
|
||||
import io.xpipe.app.fxcomps.impl.VerticalComp;
|
||||
|
|
|
@ -2,7 +2,7 @@ package io.xpipe.app.prefs;
|
|||
|
||||
import io.xpipe.app.core.AppCache;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
|
||||
import javafx.scene.control.Alert;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ package io.xpipe.app.prefs;
|
|||
|
||||
import io.xpipe.app.core.AppCache;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.core.mode.OperationMode;
|
||||
import io.xpipe.app.ext.PrefsChoiceValue;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ package io.xpipe.app.update;
|
|||
|
||||
import io.xpipe.app.comp.base.MarkdownComp;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
|
|
|
@ -2,7 +2,7 @@ package io.xpipe.app.update;
|
|||
|
||||
import io.xpipe.app.comp.base.MarkdownComp;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package io.xpipe.app.util;
|
|||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppStyle;
|
||||
import io.xpipe.app.core.AppTheme;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.fxcomps.impl.SecretFieldComp;
|
||||
import io.xpipe.core.util.InPlaceSecretValue;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.xpipe.app.util;
|
||||
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.fxcomps.impl.LabelComp;
|
||||
import io.xpipe.app.fxcomps.impl.SecretFieldComp;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.xpipe.app.util;
|
||||
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.xpipe.app.util;
|
||||
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.core.process.ShellControl;
|
||||
import io.xpipe.core.util.ProxyManagerProvider;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package io.xpipe.app.util;
|
|||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.core.AppStyle;
|
||||
import io.xpipe.app.core.AppTheme;
|
||||
import io.xpipe.app.core.AppWindowHelper;
|
||||
import io.xpipe.app.core.window.AppWindowHelper;
|
||||
import io.xpipe.app.fxcomps.impl.SecretFieldComp;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
|
|
|
@ -44,6 +44,7 @@ open module io.xpipe.app {
|
|||
exports io.xpipe.app.browser.session;
|
||||
exports io.xpipe.app.browser.fs;
|
||||
exports io.xpipe.app.browser.file;
|
||||
exports io.xpipe.app.core.window;
|
||||
|
||||
requires com.sun.jna;
|
||||
requires com.sun.jna.platform;
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
}
|
||||
|
||||
.prefs {
|
||||
-fx-background-color: -color-bg-default;
|
||||
-fx-background-color: transparent;
|
||||
}
|
||||
|
||||
.prefs .sidebar {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.scroll-bar:vertical {
|
||||
-fx-pref-width: 0.3em;
|
||||
-fx-padding: 0.3em 0 0.3em 0;
|
||||
-fx-padding: 0.4em 0 0.3em 0;
|
||||
-fx-background-color: transparent;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,30 +1,44 @@
|
|||
.sidebar-comp {
|
||||
-fx-border-width: 0 0 0 1px;
|
||||
-fx-border-color: -color-border-default;
|
||||
-fx-padding: 0;
|
||||
-fx-background-insets: 0;
|
||||
-fx-border-width: 0 0 0 1px;
|
||||
-fx-border-color: -color-border-default;
|
||||
}
|
||||
|
||||
.root:dark .sidebar-comp {
|
||||
-fx-background-color: derive(-color-bg-default, 10%);
|
||||
}
|
||||
|
||||
.root:light .sidebar-comp {
|
||||
-fx-background-color: derive(-color-bg-default, -1%);
|
||||
}
|
||||
|
||||
.root:seamless-frame .sidebar-comp {
|
||||
-fx-border-width: 0;
|
||||
-fx-border-color: transparent;
|
||||
-fx-background-color: transparent;
|
||||
}
|
||||
|
||||
.sidebar-comp .icon-button-comp, .sidebar-comp .button {
|
||||
-fx-background-radius: 0;
|
||||
-fx-background-insets: 0;
|
||||
-fx-background-color: -color-neutral-subtle;
|
||||
-fx-background-color: transparent;
|
||||
}
|
||||
|
||||
.sidebar-comp .button:disabled {
|
||||
-fx-opacity: 1.0;
|
||||
}
|
||||
|
||||
.sidebar-comp .icon-button-comp:hover, .root:key-navigation .sidebar-comp .icon-button-comp:focused {
|
||||
.root .sidebar-comp .icon-button-comp:hover, .root:key-navigation .sidebar-comp .icon-button-comp:focused {
|
||||
-fx-background-color: -color-neutral-muted;
|
||||
}
|
||||
|
||||
.sidebar-comp .icon-button-comp:selected {
|
||||
.root .sidebar-comp .icon-button-comp:selected {
|
||||
-fx-background-color: -color-neutral-muted;
|
||||
}
|
||||
|
||||
.sidebar-comp .icon-button-comp {
|
||||
-fx-padding: 1.1em;
|
||||
-fx-padding: 1em;
|
||||
}
|
||||
|
||||
.sidebar-comp .icon-button-comp .vbox {
|
||||
|
|
|
@ -5,6 +5,33 @@
|
|||
}
|
||||
*/
|
||||
|
||||
.root {
|
||||
-fx-background-color: transparent;
|
||||
}
|
||||
|
||||
.root:dark .background {
|
||||
-fx-background-color: derive(-color-bg-default, 1%);
|
||||
}
|
||||
|
||||
.root:light .background {
|
||||
-fx-background-color: derive(-color-bg-default, -9%);
|
||||
}
|
||||
|
||||
.root:seamless-frame .background {
|
||||
-fx-background-insets: 5 0 0 0;
|
||||
-fx-border-insets: 5 0 0 0;
|
||||
-fx-background-radius: 0 10 0 0;
|
||||
-fx-border-radius: 0 10 0 0;
|
||||
-fx-border-width: 1 1 0 0;
|
||||
-fx-border-color: -color-border-default;
|
||||
-fx-padding: 0 2 0 0;
|
||||
}
|
||||
|
||||
.root:seamless-frame .background > * {
|
||||
-fx-background-radius: 0 10 0 0;
|
||||
-fx-border-radius: 0 10 0 0;
|
||||
}
|
||||
|
||||
.toggle-switch:has-graphic .label {
|
||||
-fx-font-size: 1.7em;
|
||||
}
|
||||
|
@ -17,14 +44,6 @@
|
|||
-fx-background-color: transparent;
|
||||
}
|
||||
|
||||
.root:dark.background {
|
||||
-fx-background-color: derive(-color-bg-default, 1%);
|
||||
}
|
||||
|
||||
.root:light.background {
|
||||
-fx-background-color: derive(-color-bg-default, -9%);
|
||||
}
|
||||
|
||||
.edit-button.icon-button-comp {
|
||||
-fx-background-radius: 4px;
|
||||
-fx-border-width: 1px;
|
||||
|
|
Loading…
Reference in a new issue