From 4d43cc5fd07bddfd0ae90c0b2927dfd225374094 Mon Sep 17 00:00:00 2001 From: crschnick Date: Wed, 19 Jun 2024 20:26:19 +0000 Subject: [PATCH] Merge branch native-window into master --- .../app/browser/BrowserSelectionListComp.java | 2 +- .../xpipe/app/browser/file/BrowserAlerts.java | 2 +- .../browser/session/BrowserChooserComp.java | 2 +- .../java/io/xpipe/app/comp/AppLayoutComp.java | 3 +- .../io/xpipe/app/comp/base/DialogComp.java | 2 +- .../xpipe/app/comp/base/SideMenuBarComp.java | 1 - .../app/comp/store/StoreCreationComp.java | 2 +- app/src/main/java/io/xpipe/app/core/App.java | 4 +- .../xpipe/app/core/AppActionLinkDetector.java | 1 + .../java/io/xpipe/app/core/AppGreetings.java | 1 + .../main/java/io/xpipe/app/core/AppI18n.java | 1 + .../main/java/io/xpipe/app/core/AppTheme.java | 55 ++----------- .../io/xpipe/app/core/check/AppAvCheck.java | 1 + .../io/xpipe/app/core/check/AppPtbCheck.java | 2 +- .../java/io/xpipe/app/core/mode/GuiMode.java | 2 +- .../io/xpipe/app/core/mode/PlatformMode.java | 2 + .../app/core/{ => window}/AppMainWindow.java | 15 ++-- .../core/{ => window}/AppWindowHelper.java | 3 +- .../app/core/window/DmwaWindowAttribute.java | 16 ++++ .../core/window/DwmSystemBackDropType.java | 18 ++++ .../app/core/window/ModifiedAlertStage.java | 41 ++++++++++ .../xpipe/app/core/window/ModifiedStage.java | 82 +++++++++++++++++++ .../window/NativeWinWindowControl.java} | 42 +++++----- .../ContextualFileReferenceChoiceComp.java | 2 +- .../app/fxcomps/impl/PrettyImageComp.java | 11 ++- .../xpipe/app/fxcomps/impl/PrettySvgComp.java | 11 ++- .../io/xpipe/app/issue/ErrorHandlerComp.java | 2 +- .../xpipe/app/issue/TerminalErrorHandler.java | 1 + .../io/xpipe/app/issue/UserReportComp.java | 1 + .../io/xpipe/app/prefs/AboutCategory.java | 2 +- .../io/xpipe/app/prefs/ClearCacheAlert.java | 2 +- .../xpipe/app/prefs/CloseBehaviourAlert.java | 2 +- .../app/update/UpdateAvailableAlert.java | 2 +- .../app/update/UpdateChangelogAlert.java | 2 +- .../java/io/xpipe/app/util/AskpassAlert.java | 2 +- .../io/xpipe/app/util/LockChangeAlert.java | 2 +- .../io/xpipe/app/util/MacOsPermissions.java | 2 +- .../app/util/ProxyManagerProviderImpl.java | 2 +- .../java/io/xpipe/app/util/UnlockAlert.java | 2 +- app/src/main/java/module-info.java | 1 + .../io/xpipe/app/resources/style/prefs.css | 2 +- .../xpipe/app/resources/style/scrollbar.css | 2 +- .../app/resources/style/sidebar-comp.css | 26 ++++-- .../io/xpipe/app/resources/style/style.css | 35 ++++++-- 44 files changed, 290 insertions(+), 124 deletions(-) rename app/src/main/java/io/xpipe/app/core/{ => window}/AppMainWindow.java (96%) rename app/src/main/java/io/xpipe/app/core/{ => window}/AppWindowHelper.java (99%) create mode 100644 app/src/main/java/io/xpipe/app/core/window/DmwaWindowAttribute.java create mode 100644 app/src/main/java/io/xpipe/app/core/window/DwmSystemBackDropType.java create mode 100644 app/src/main/java/io/xpipe/app/core/window/ModifiedAlertStage.java create mode 100644 app/src/main/java/io/xpipe/app/core/window/ModifiedStage.java rename app/src/main/java/io/xpipe/app/{util/WindowControl.java => core/window/NativeWinWindowControl.java} (60%) diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserSelectionListComp.java b/app/src/main/java/io/xpipe/app/browser/BrowserSelectionListComp.java index decdb829b..59b07136a 100644 --- a/app/src/main/java/io/xpipe/app/browser/BrowserSelectionListComp.java +++ b/app/src/main/java/io/xpipe/app/browser/BrowserSelectionListComp.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/browser/file/BrowserAlerts.java b/app/src/main/java/io/xpipe/app/browser/file/BrowserAlerts.java index 41a975ab2..10f44e812 100644 --- a/app/src/main/java/io/xpipe/app/browser/file/BrowserAlerts.java +++ b/app/src/main/java/io/xpipe/app/browser/file/BrowserAlerts.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/browser/session/BrowserChooserComp.java b/app/src/main/java/io/xpipe/app/browser/session/BrowserChooserComp.java index 0f1c2bf94..25701b5b4 100644 --- a/app/src/main/java/io/xpipe/app/browser/session/BrowserChooserComp.java +++ b/app/src/main/java/io/xpipe/app/browser/session/BrowserChooserComp.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/comp/AppLayoutComp.java b/app/src/main/java/io/xpipe/app/comp/AppLayoutComp.java index de51a6489..884f7cb9b 100644 --- a/app/src/main/java/io/xpipe/app/comp/AppLayoutComp.java +++ b/app/src/main/java/io/xpipe/app/comp/AppLayoutComp.java @@ -34,13 +34,13 @@ public class AppLayoutComp extends Comp> { }, 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> { } }); AppFont.normal(pane); + pane.getStyleClass().add("layout"); return new SimpleCompStructure<>(pane); } } diff --git a/app/src/main/java/io/xpipe/app/comp/base/DialogComp.java b/app/src/main/java/io/xpipe/app/comp/base/DialogComp.java index 853a809c5..7eebc845a 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/DialogComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/DialogComp.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java b/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java index a6f7003b6..d862a9d48 100644 --- a/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java +++ b/app/src/main/java/io/xpipe/app/comp/base/SideMenuBarComp.java @@ -196,7 +196,6 @@ public class SideMenuBarComp extends Comp> { 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); } diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreCreationComp.java b/app/src/main/java/io/xpipe/app/comp/store/StoreCreationComp.java index a9588494a..2e4d7cfae 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreCreationComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreCreationComp.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/core/App.java b/app/src/main/java/io/xpipe/app/core/App.java index a7b046d29..a159fa684 100644 --- a/app/src/main/java/io/xpipe/app/core/App.java +++ b/app/src/main/java/io/xpipe/app/core/App.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/core/AppActionLinkDetector.java b/app/src/main/java/io/xpipe/app/core/AppActionLinkDetector.java index ff7e7909e..a960cf7d9 100644 --- a/app/src/main/java/io/xpipe/app/core/AppActionLinkDetector.java +++ b/app/src/main/java/io/xpipe/app/core/AppActionLinkDetector.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/core/AppGreetings.java b/app/src/main/java/io/xpipe/app/core/AppGreetings.java index 8cb93ac9c..1d94ed99d 100644 --- a/app/src/main/java/io/xpipe/app/core/AppGreetings.java +++ b/app/src/main/java/io/xpipe/app/core/AppGreetings.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/core/AppI18n.java b/app/src/main/java/io/xpipe/app/core/AppI18n.java index f70c6423c..80f168cab 100644 --- a/app/src/main/java/io/xpipe/app/core/AppI18n.java +++ b/app/src/main/java/io/xpipe/app/core/AppI18n.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/core/AppTheme.java b/app/src/main/java/io/xpipe/app/core/AppTheme.java index dc79cbe2f..b54aa8403 100644 --- a/app/src/main/java/io/xpipe/app/core/AppTheme.java +++ b/app/src/main/java/io/xpipe/app/core/AppTheme.java @@ -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 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; diff --git a/app/src/main/java/io/xpipe/app/core/check/AppAvCheck.java b/app/src/main/java/io/xpipe/app/core/check/AppAvCheck.java index 756634d4f..4dff8398a 100644 --- a/app/src/main/java/io/xpipe/app/core/check/AppAvCheck.java +++ b/app/src/main/java/io/xpipe/app/core/check/AppAvCheck.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/core/check/AppPtbCheck.java b/app/src/main/java/io/xpipe/app/core/check/AppPtbCheck.java index d45e89820..a31d96ab5 100644 --- a/app/src/main/java/io/xpipe/app/core/check/AppPtbCheck.java +++ b/app/src/main/java/io/xpipe/app/core/check/AppPtbCheck.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/core/mode/GuiMode.java b/app/src/main/java/io/xpipe/app/core/mode/GuiMode.java index 5a559f0bd..4cc8238f9 100644 --- a/app/src/main/java/io/xpipe/app/core/mode/GuiMode.java +++ b/app/src/main/java/io/xpipe/app/core/mode/GuiMode.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/core/mode/PlatformMode.java b/app/src/main/java/io/xpipe/app/core/mode/PlatformMode.java index b5cb69efe..3680586c9 100644 --- a/app/src/main/java/io/xpipe/app/core/mode/PlatformMode.java +++ b/app/src/main/java/io/xpipe/app/core/mode/PlatformMode.java @@ -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 ..."); diff --git a/app/src/main/java/io/xpipe/app/core/AppMainWindow.java b/app/src/main/java/io/xpipe/app/core/window/AppMainWindow.java similarity index 96% rename from app/src/main/java/io/xpipe/app/core/AppMainWindow.java rename to app/src/main/java/io/xpipe/app/core/window/AppMainWindow.java index c104aa679..f0747e691 100644 --- a/app/src/main/java/io/xpipe/app/core/AppMainWindow.java +++ b/app/src/main/java/io/xpipe/app/core/window/AppMainWindow.java @@ -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"); diff --git a/app/src/main/java/io/xpipe/app/core/AppWindowHelper.java b/app/src/main/java/io/xpipe/app/core/window/AppWindowHelper.java similarity index 99% rename from app/src/main/java/io/xpipe/app/core/AppWindowHelper.java rename to app/src/main/java/io/xpipe/app/core/window/AppWindowHelper.java index 12e94e434..62f43b6eb 100644 --- a/app/src/main/java/io/xpipe/app/core/AppWindowHelper.java +++ b/app/src/main/java/io/xpipe/app/core/window/AppWindowHelper.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/core/window/DmwaWindowAttribute.java b/app/src/main/java/io/xpipe/app/core/window/DmwaWindowAttribute.java new file mode 100644 index 000000000..5b4e09382 --- /dev/null +++ b/app/src/main/java/io/xpipe/app/core/window/DmwaWindowAttribute.java @@ -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; + } +} diff --git a/app/src/main/java/io/xpipe/app/core/window/DwmSystemBackDropType.java b/app/src/main/java/io/xpipe/app/core/window/DwmSystemBackDropType.java new file mode 100644 index 000000000..0b9a1b608 --- /dev/null +++ b/app/src/main/java/io/xpipe/app/core/window/DwmSystemBackDropType.java @@ -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; + } +} diff --git a/app/src/main/java/io/xpipe/app/core/window/ModifiedAlertStage.java b/app/src/main/java/io/xpipe/app/core/window/ModifiedAlertStage.java new file mode 100644 index 000000000..bc3a0db5b --- /dev/null +++ b/app/src/main/java/io/xpipe/app/core/window/ModifiedAlertStage.java @@ -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); + } +} diff --git a/app/src/main/java/io/xpipe/app/core/window/ModifiedStage.java b/app/src/main/java/io/xpipe/app/core/window/ModifiedStage.java new file mode 100644 index 000000000..0d64a65ff --- /dev/null +++ b/app/src/main/java/io/xpipe/app/core/window/ModifiedStage.java @@ -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 list = (ObservableList) windowsField.get(null); + list.addListener((ListChangeListener) 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(); + }); + } +} diff --git a/app/src/main/java/io/xpipe/app/util/WindowControl.java b/app/src/main/java/io/xpipe/app/core/window/NativeWinWindowControl.java similarity index 60% rename from app/src/main/java/io/xpipe/app/util/WindowControl.java rename to app/src/main/java/io/xpipe/app/core/window/NativeWinWindowControl.java index a36581d18..16878360e 100644 --- a/app/src/main/java/io/xpipe/app/util/WindowControl.java +++ b/app/src/main/java/io/xpipe/app/core/window/NativeWinWindowControl.java @@ -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); diff --git a/app/src/main/java/io/xpipe/app/fxcomps/impl/ContextualFileReferenceChoiceComp.java b/app/src/main/java/io/xpipe/app/fxcomps/impl/ContextualFileReferenceChoiceComp.java index 65a02dbe3..77d47c38e 100644 --- a/app/src/main/java/io/xpipe/app/fxcomps/impl/ContextualFileReferenceChoiceComp.java +++ b/app/src/main/java/io/xpipe/app/fxcomps/impl/ContextualFileReferenceChoiceComp.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/fxcomps/impl/PrettyImageComp.java b/app/src/main/java/io/xpipe/app/fxcomps/impl/PrettyImageComp.java index cc741e629..97980fd3b 100644 --- a/app/src/main/java/io/xpipe/app/fxcomps/impl/PrettyImageComp.java +++ b/app/src/main/java/io/xpipe/app/fxcomps/impl/PrettyImageComp.java @@ -93,8 +93,9 @@ public class PrettyImageComp extends SimpleComp { stack.getChildren().add(storeIcon); Consumer 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); diff --git a/app/src/main/java/io/xpipe/app/fxcomps/impl/PrettySvgComp.java b/app/src/main/java/io/xpipe/app/fxcomps/impl/PrettySvgComp.java index 3fb8cf80b..6b4409a74 100644 --- a/app/src/main/java/io/xpipe/app/fxcomps/impl/PrettySvgComp.java +++ b/app/src/main/java/io/xpipe/app/fxcomps/impl/PrettySvgComp.java @@ -88,17 +88,20 @@ public class PrettySvgComp extends SimpleComp { } Consumer 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); diff --git a/app/src/main/java/io/xpipe/app/issue/ErrorHandlerComp.java b/app/src/main/java/io/xpipe/app/issue/ErrorHandlerComp.java index 5b43cbcf0..967f0788e 100644 --- a/app/src/main/java/io/xpipe/app/issue/ErrorHandlerComp.java +++ b/app/src/main/java/io/xpipe/app/issue/ErrorHandlerComp.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/issue/TerminalErrorHandler.java b/app/src/main/java/io/xpipe/app/issue/TerminalErrorHandler.java index c01fbe62c..991f64549 100644 --- a/app/src/main/java/io/xpipe/app/issue/TerminalErrorHandler.java +++ b/app/src/main/java/io/xpipe/app/issue/TerminalErrorHandler.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/issue/UserReportComp.java b/app/src/main/java/io/xpipe/app/issue/UserReportComp.java index 693cd02a9..f11478d25 100644 --- a/app/src/main/java/io/xpipe/app/issue/UserReportComp.java +++ b/app/src/main/java/io/xpipe/app/issue/UserReportComp.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/prefs/AboutCategory.java b/app/src/main/java/io/xpipe/app/prefs/AboutCategory.java index 1e3c6039a..5b363285e 100644 --- a/app/src/main/java/io/xpipe/app/prefs/AboutCategory.java +++ b/app/src/main/java/io/xpipe/app/prefs/AboutCategory.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/prefs/ClearCacheAlert.java b/app/src/main/java/io/xpipe/app/prefs/ClearCacheAlert.java index a64de0201..8645ac1e5 100644 --- a/app/src/main/java/io/xpipe/app/prefs/ClearCacheAlert.java +++ b/app/src/main/java/io/xpipe/app/prefs/ClearCacheAlert.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/prefs/CloseBehaviourAlert.java b/app/src/main/java/io/xpipe/app/prefs/CloseBehaviourAlert.java index 0a4e198dc..7b3b4160e 100644 --- a/app/src/main/java/io/xpipe/app/prefs/CloseBehaviourAlert.java +++ b/app/src/main/java/io/xpipe/app/prefs/CloseBehaviourAlert.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/update/UpdateAvailableAlert.java b/app/src/main/java/io/xpipe/app/update/UpdateAvailableAlert.java index 7f19a094e..77b17818b 100644 --- a/app/src/main/java/io/xpipe/app/update/UpdateAvailableAlert.java +++ b/app/src/main/java/io/xpipe/app/update/UpdateAvailableAlert.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/update/UpdateChangelogAlert.java b/app/src/main/java/io/xpipe/app/update/UpdateChangelogAlert.java index 5b524d49b..033ba5d6f 100644 --- a/app/src/main/java/io/xpipe/app/update/UpdateChangelogAlert.java +++ b/app/src/main/java/io/xpipe/app/update/UpdateChangelogAlert.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/util/AskpassAlert.java b/app/src/main/java/io/xpipe/app/util/AskpassAlert.java index 89a350d6a..7a8a37d1b 100644 --- a/app/src/main/java/io/xpipe/app/util/AskpassAlert.java +++ b/app/src/main/java/io/xpipe/app/util/AskpassAlert.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/util/LockChangeAlert.java b/app/src/main/java/io/xpipe/app/util/LockChangeAlert.java index 99107afc2..b575bf0f3 100644 --- a/app/src/main/java/io/xpipe/app/util/LockChangeAlert.java +++ b/app/src/main/java/io/xpipe/app/util/LockChangeAlert.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/util/MacOsPermissions.java b/app/src/main/java/io/xpipe/app/util/MacOsPermissions.java index 397353d3e..53a181e4b 100644 --- a/app/src/main/java/io/xpipe/app/util/MacOsPermissions.java +++ b/app/src/main/java/io/xpipe/app/util/MacOsPermissions.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/util/ProxyManagerProviderImpl.java b/app/src/main/java/io/xpipe/app/util/ProxyManagerProviderImpl.java index 686604dba..760ca6254 100644 --- a/app/src/main/java/io/xpipe/app/util/ProxyManagerProviderImpl.java +++ b/app/src/main/java/io/xpipe/app/util/ProxyManagerProviderImpl.java @@ -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; diff --git a/app/src/main/java/io/xpipe/app/util/UnlockAlert.java b/app/src/main/java/io/xpipe/app/util/UnlockAlert.java index f3aadc1bc..1c3381970 100644 --- a/app/src/main/java/io/xpipe/app/util/UnlockAlert.java +++ b/app/src/main/java/io/xpipe/app/util/UnlockAlert.java @@ -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; diff --git a/app/src/main/java/module-info.java b/app/src/main/java/module-info.java index b29466bb8..e1fd3728f 100644 --- a/app/src/main/java/module-info.java +++ b/app/src/main/java/module-info.java @@ -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; diff --git a/app/src/main/resources/io/xpipe/app/resources/style/prefs.css b/app/src/main/resources/io/xpipe/app/resources/style/prefs.css index 2323ba028..19e314289 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/prefs.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/prefs.css @@ -27,7 +27,7 @@ } .prefs { - -fx-background-color: -color-bg-default; + -fx-background-color: transparent; } .prefs .sidebar { diff --git a/app/src/main/resources/io/xpipe/app/resources/style/scrollbar.css b/app/src/main/resources/io/xpipe/app/resources/style/scrollbar.css index ae298c5f5..95649476b 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/scrollbar.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/scrollbar.css @@ -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; } diff --git a/app/src/main/resources/io/xpipe/app/resources/style/sidebar-comp.css b/app/src/main/resources/io/xpipe/app/resources/style/sidebar-comp.css index cc49c10fd..37a0487fe 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/sidebar-comp.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/sidebar-comp.css @@ -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 { diff --git a/app/src/main/resources/io/xpipe/app/resources/style/style.css b/app/src/main/resources/io/xpipe/app/resources/style/style.css index 2d8968471..ff1ce11de 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/style.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/style.css @@ -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;