Merge branch native-window into master

This commit is contained in:
crschnick 2024-06-19 20:26:19 +00:00
parent 914f724577
commit 4d43cc5fd0
44 changed files with 290 additions and 124 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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 ...");

View file

@ -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");

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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();
});
}
}

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -27,7 +27,7 @@
}
.prefs {
-fx-background-color: -color-bg-default;
-fx-background-color: transparent;
}
.prefs .sidebar {

View file

@ -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;
}

View file

@ -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 {

View file

@ -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;