diff --git a/v2rayN/v2rayN.Desktop/App.axaml b/v2rayN/v2rayN.Desktop/App.axaml
index 21204f60..fd648056 100644
--- a/v2rayN/v2rayN.Desktop/App.axaml
+++ b/v2rayN/v2rayN.Desktop/App.axaml
@@ -22,6 +22,24 @@
+
+
+
diff --git a/v2rayN/v2rayN.Desktop/Base/WindowBase.cs b/v2rayN/v2rayN.Desktop/Base/WindowBase.cs
index d1419b30..86ba979e 100644
--- a/v2rayN/v2rayN.Desktop/Base/WindowBase.cs
+++ b/v2rayN/v2rayN.Desktop/Base/WindowBase.cs
@@ -2,8 +2,17 @@ namespace v2rayN.Desktop.Base;
public class WindowBase : ReactiveWindow where TViewModel : class
{
+ private Border? _linuxTitleBar;
+ private Control? _linuxTitleBarDragRegion;
+ private Button? _linuxTitleBarCloseButton;
+
public WindowBase()
{
+ if (Utils.IsLinux())
+ {
+ SystemDecorations = SystemDecorations.BorderOnly;
+ }
+
Loaded += OnLoaded;
}
@@ -34,10 +43,13 @@ public class WindowBase : ReactiveWindow where TViewMode
Position = new PixelPoint((int)x, (int)y);
}
catch { }
+
+ ConfigureLinuxTitleBar();
}
protected override void OnClosed(EventArgs e)
{
+ ReleaseLinuxTitleBar();
base.OnClosed(e);
try
{
@@ -45,4 +57,67 @@ public class WindowBase : ReactiveWindow where TViewMode
}
catch { }
}
+
+ protected virtual void HandleLinuxTitleBarClose()
+ {
+ Close();
+ }
+
+ private void ConfigureLinuxTitleBar()
+ {
+ if (!Utils.IsLinux())
+ {
+ return;
+ }
+
+ _linuxTitleBar ??= this.FindControl("linuxTitleBar");
+ if (_linuxTitleBar == null)
+ {
+ return;
+ }
+
+ _linuxTitleBar.IsVisible = true;
+
+ _linuxTitleBarDragRegion ??= this.FindControl("linuxTitleBarDragRegion");
+ if (_linuxTitleBarDragRegion != null)
+ {
+ _linuxTitleBarDragRegion.PointerPressed -= LinuxTitleBar_PointerPressed;
+ _linuxTitleBarDragRegion.PointerPressed += LinuxTitleBar_PointerPressed;
+ }
+
+ _linuxTitleBarCloseButton ??= this.FindControl