mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
114 lines
4.1 KiB
C#
114 lines
4.1 KiB
C#
using Avalonia;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Platform;
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace Mesen.Config
|
|
{
|
|
public class BaseWindowConfig<T> : BaseConfig<T> where T : class
|
|
{
|
|
public PixelSize WindowSize { get; set; } = new PixelSize(0, 0);
|
|
public PixelPoint WindowLocation { get; set; } = new PixelPoint(0, 0);
|
|
public bool WindowIsMaximized { get; set; } = false;
|
|
|
|
private PixelRect _restoreBounds = PixelRect.Empty;
|
|
private bool _needPositionCheck = false;
|
|
|
|
public void SaveWindowSettings(Window wnd)
|
|
{
|
|
if(wnd.WindowState == WindowState.Normal) {
|
|
WindowLocation = wnd.Position;
|
|
WindowSize = new PixelSize((int)wnd.ClientSize.Width, (int)wnd.ClientSize.Height);
|
|
} else if(!_restoreBounds.IsEmpty) {
|
|
WindowLocation = _restoreBounds.Position;
|
|
WindowSize = _restoreBounds.Size;
|
|
}
|
|
|
|
WindowIsMaximized = wnd.WindowState == WindowState.Maximized;
|
|
}
|
|
|
|
public void LoadWindowSettings(Window wnd)
|
|
{
|
|
//Update _restoreBounds when size/position changes
|
|
wnd.GetPropertyChangedObservable(Window.ClientSizeProperty).Subscribe(x => UpdateRestoreBounds(wnd));
|
|
wnd.PositionChanged += (s, e) => UpdateRestoreBounds(wnd);
|
|
|
|
if(WindowSize.Width != 0 && WindowSize.Height != 0) {
|
|
if(WindowSize.Width * WindowSize.Height < 400) {
|
|
//Window is too small, reset to a default size
|
|
WindowSize = new PixelSize(300, 300);
|
|
}
|
|
|
|
PixelRect wndRect = new PixelRect(WindowLocation, WindowSize);
|
|
|
|
Screen? screen = wnd.Screens.ScreenFromBounds(wndRect);
|
|
if(screen == null) {
|
|
//Window is not on any screen, move it to the top left of the first screen
|
|
wnd.Position = wnd.Screens.All[0].WorkingArea.TopLeft;
|
|
} else {
|
|
//Window top left corner is offscreen, adjust position
|
|
if(WindowLocation.Y < screen.WorkingArea.Position.Y) {
|
|
WindowLocation = WindowLocation.WithY(screen.WorkingArea.Position.Y);
|
|
}
|
|
if(WindowLocation.X < screen.WorkingArea.Position.X) {
|
|
WindowLocation = WindowLocation.WithX(screen.WorkingArea.Position.X);
|
|
}
|
|
|
|
wndRect = new PixelRect(WindowLocation, WindowSize);
|
|
PixelRect intersect = screen.WorkingArea.Intersect(wndRect);
|
|
if(intersect.Width * intersect.Height < wndRect.Width * wndRect.Height / 2) {
|
|
//More than half the window is offscreen, move it to the top left corner to be safe
|
|
wnd.Position = wnd.Screens.All[0].WorkingArea.TopLeft;
|
|
} else {
|
|
wnd.Position = WindowLocation;
|
|
}
|
|
}
|
|
|
|
wnd.Width = WindowSize.Width;
|
|
wnd.Height = WindowSize.Height;
|
|
|
|
wnd.Opened += (s, e) => {
|
|
if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) {
|
|
//Set position again after opening
|
|
//Fixes KDE (or X11?) not showing the window in the specified position
|
|
_needPositionCheck = true;
|
|
wnd.Position = WindowLocation;
|
|
} else {
|
|
//Also needed for Windows, otherwise window slightly shifts to the right
|
|
wnd.Position = WindowLocation;
|
|
}
|
|
|
|
if(!_needPositionCheck && WindowIsMaximized) {
|
|
wnd.WindowState = WindowState.Maximized;
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
private void UpdateRestoreBounds(Window wnd)
|
|
{
|
|
if(_needPositionCheck) {
|
|
//Linux doesn't set the position correctly (because of title bar, etc.), adjust it to what it should be
|
|
//See Avalonia bug: github.com/AvaloniaUI/Avalonia/issues/8161
|
|
_needPositionCheck = false;
|
|
if(wnd.Position.Y >= WindowLocation.Y && wnd.Position.X >= WindowLocation.X) {
|
|
wnd.Position = new PixelPoint(
|
|
WindowLocation.X - (wnd.Position.X - WindowLocation.X),
|
|
WindowLocation.Y - (wnd.Position.Y - WindowLocation.Y)
|
|
);
|
|
}
|
|
|
|
if(WindowIsMaximized) {
|
|
//Maximize after the position is fixed, otherwise when the state goes back to normal, window position will be offset
|
|
wnd.WindowState = WindowState.Maximized;
|
|
}
|
|
}
|
|
|
|
if(wnd.WindowState == WindowState.Normal && (wnd.Position.X > 0 || wnd.Position.Y > 0) && wnd.PlatformImpl != null && wnd.Width != wnd.Screens.ScreenFromWindow(wnd.PlatformImpl)?.Bounds.Width) {
|
|
//If window is not maximized/minimized, save current position+size
|
|
_restoreBounds = new PixelRect(wnd.Position.X, wnd.Position.Y, (int)wnd.Width, (int)wnd.Height);
|
|
}
|
|
}
|
|
}
|
|
}
|