Skip to content

Commit ee5817d

Browse files
committed
fix: linux splitscreen mode window layout
1 parent 9fea665 commit ee5817d

3 files changed

Lines changed: 88 additions & 2 deletions

File tree

src/Native/Linux.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,58 @@ private string FindExecutable(string filename)
171171
return File.Exists(local) ? local : string.Empty;
172172
}
173173
}
174+
175+
[SupportedOSPlatform("linux")]
176+
public static class LinuxUtilities
177+
{
178+
public const string TiledFrameClass = "window_frame_tiled";
179+
180+
private const int EdgeTolerance = 2;
181+
182+
public static void UpdateCustomWindowFrameStyle(Window window)
183+
{
184+
if (OS.UseSystemWindowFrame || !window.Classes.Contains("custom_window_frame"))
185+
return;
186+
187+
var tiled = IsWindowTiledOrSnapped(window);
188+
if (tiled)
189+
{
190+
if (!window.Classes.Contains(TiledFrameClass))
191+
window.Classes.Add(TiledFrameClass);
192+
}
193+
else if (window.Classes.Contains(TiledFrameClass))
194+
{
195+
window.Classes.Remove(TiledFrameClass);
196+
}
197+
}
198+
199+
private static bool IsWindowTiledOrSnapped(Window window)
200+
{
201+
if (window.WindowState is WindowState.Maximized or WindowState.FullScreen)
202+
return false;
203+
204+
if (window.Screens is not { } screens)
205+
return false;
206+
207+
var screen = screens.ScreenFromWindow(window);
208+
if (screen == null)
209+
return false;
210+
211+
var workArea = screen.WorkingArea;
212+
var size = PixelSize.FromSize(new Size(window.Width, window.Height), window.DesktopScaling);
213+
var frame = new PixelRect(window.Position, size);
214+
215+
var edgeCount = 0;
216+
if (Math.Abs(frame.X - workArea.X) <= EdgeTolerance)
217+
edgeCount++;
218+
if (Math.Abs(frame.Right - workArea.Right) <= EdgeTolerance)
219+
edgeCount++;
220+
if (Math.Abs(frame.Y - workArea.Y) <= EdgeTolerance)
221+
edgeCount++;
222+
if (Math.Abs(frame.Bottom - workArea.Bottom) <= EdgeTolerance)
223+
edgeCount++;
224+
225+
return edgeCount >= 2;
226+
}
227+
}
174228
}

src/Resources/Styles.axaml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@
126126
Cursor="BottomRightCorner"
127127
Tag="{x:Static WindowEdge.SouthEast}"/>
128128

129-
<Grid Margin="{TemplateBinding Padding}" Effect="drop-shadow(0 0 12 #60000000)">
129+
<Grid x:Name="PART_ContentHost" Margin="{TemplateBinding Padding}" Effect="drop-shadow(0 0 12 #60000000)">
130130
<Border x:Name="PART_ContentRoot"
131131
Background="{DynamicResource Brush.Window}"
132132
BorderBrush="{DynamicResource Brush.WindowBorder}"
@@ -155,7 +155,15 @@
155155
</Setter>
156156
</Style>
157157

158-
<Style Selector="Window.custom_window_frame[WindowState=Maximized]">
158+
<Style Selector="Window.custom_window_frame.window_frame_tiled /template/ Grid#PART_ContentHost">
159+
<Setter Property="Effect" Value="{x:Null}"/>
160+
</Style>
161+
162+
<Style Selector="Window.custom_window_frame.window_frame_tiled /template/ Border.resize_border">
163+
<Setter Property="ZIndex" Value="1"/>
164+
</Style>
165+
166+
<Style Selector="Window.custom_window_frame[WindowState=Maximized], Window.custom_window_frame.window_frame_tiled">
159167
<Setter Property="Padding" Value="0"/>
160168
<Setter Property="CornerRadius" Value="0"/>
161169
</Style>

src/Views/ChromelessWindow.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ public ChromelessWindow()
2626
{
2727
Focusable = true;
2828
Native.OS.SetupForWindow(this);
29+
30+
if (OperatingSystem.IsLinux() && !UseSystemWindowFrame)
31+
{
32+
PositionChanged += (_, _) => Native.LinuxUtilities.UpdateCustomWindowFrameStyle(this);
33+
}
2934
}
3035

3136
public void BeginMoveWindow(object _, PointerPressedEventArgs e)
@@ -81,6 +86,16 @@ protected override void OnLoaded(RoutedEventArgs e)
8186

8287
if (OperatingSystem.IsWindows())
8388
Native.Win64Utilities.FixWindowFrame(this);
89+
else if (OperatingSystem.IsLinux())
90+
Native.LinuxUtilities.UpdateCustomWindowFrameStyle(this);
91+
}
92+
93+
protected override void OnSizeChanged(SizeChangedEventArgs e)
94+
{
95+
base.OnSizeChanged(e);
96+
97+
if (OperatingSystem.IsLinux())
98+
Native.LinuxUtilities.UpdateCustomWindowFrameStyle(this);
8499
}
85100

86101
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
@@ -89,6 +104,15 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang
89104

90105
if (OperatingSystem.IsWindows() && change.Property == WindowStateProperty)
91106
Native.Win64Utilities.FixWindowFrame(this);
107+
else if (OperatingSystem.IsLinux() &&
108+
Classes.Contains("custom_window_frame") &&
109+
(change.Property == WindowStateProperty ||
110+
change.Property == BoundsProperty ||
111+
change.Property == WidthProperty ||
112+
change.Property == HeightProperty))
113+
{
114+
Native.LinuxUtilities.UpdateCustomWindowFrameStyle(this);
115+
}
92116
}
93117

94118
protected override void OnKeyDown(KeyEventArgs e)

0 commit comments

Comments
 (0)