diff --git a/src/Avalonia.Controls/Platform/IWindowImpl.cs b/src/Avalonia.Controls/Platform/IWindowImpl.cs index 3f2c977718..c5d632c0f7 100644 --- a/src/Avalonia.Controls/Platform/IWindowImpl.cs +++ b/src/Avalonia.Controls/Platform/IWindowImpl.cs @@ -16,6 +16,11 @@ namespace Avalonia.Platform /// WindowState WindowState { get; set; } + /// + /// Gets or sets a method called when the changes. + /// + Action WindowStateChanged { get; set; } + /// /// Sets the title of the window. /// diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 16ee3a46b3..6814b8567e 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -136,6 +136,7 @@ namespace Avalonia.Controls : base(impl) { impl.Closing = HandleClosing; + impl.WindowStateChanged = HandleWindowStateChanged; _maxPlatformClientSize = PlatformImpl?.MaxClientSize ?? default(Size); Screens = new Screens(PlatformImpl?.Screen); } @@ -308,6 +309,18 @@ namespace Avalonia.Controls return args.Cancel; } + protected virtual void HandleWindowStateChanged(WindowState state) + { + if (state == WindowState.Minimized) + { + Renderer.Stop(); + } + else if (state == WindowState.Normal) + { + Renderer.Start(); + } + } + /// /// Hides the window but does not close it. /// diff --git a/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs b/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs index 9750b46aa2..ef16d06b60 100644 --- a/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs +++ b/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs @@ -42,6 +42,7 @@ namespace Avalonia.DesignerSupport.Remote public Func Closing { get; set; } public IPlatformHandle Handle { get; } public WindowState WindowState { get; set; } + public Action WindowStateChanged { get; set; } public Size MaxClientSize { get; } = new Size(4096, 4096); public event Action LostFocus; diff --git a/src/Avalonia.DesignerSupport/Remote/Stubs.cs b/src/Avalonia.DesignerSupport/Remote/Stubs.cs index ee8569d748..72fce0d921 100644 --- a/src/Avalonia.DesignerSupport/Remote/Stubs.cs +++ b/src/Avalonia.DesignerSupport/Remote/Stubs.cs @@ -32,6 +32,8 @@ namespace Avalonia.DesignerSupport.Remote public Point Position { get; set; } public Action PositionChanged { get; set; } public WindowState WindowState { get; set; } + public Action WindowStateChanged { get; set; } + public IRenderer CreateRenderer(IRenderRoot root) => new ImmediateRenderer(root); public void Dispose() { diff --git a/src/Gtk/Avalonia.Gtk3/WindowImpl.cs b/src/Gtk/Avalonia.Gtk3/WindowImpl.cs index 2d309e19d4..ac03816b02 100644 --- a/src/Gtk/Avalonia.Gtk3/WindowImpl.cs +++ b/src/Gtk/Avalonia.Gtk3/WindowImpl.cs @@ -43,7 +43,9 @@ namespace Avalonia.Gtk3 } } } - + + public Action WindowStateChanged { get; set; } + public IDisposable ShowDialog() { Native.GtkWindowSetModal(GtkWidget, true); diff --git a/src/OSX/Avalonia.MonoMac/WindowImpl.cs b/src/OSX/Avalonia.MonoMac/WindowImpl.cs index d01cbd6ae3..43d6918112 100644 --- a/src/OSX/Avalonia.MonoMac/WindowImpl.cs +++ b/src/OSX/Avalonia.MonoMac/WindowImpl.cs @@ -49,6 +49,8 @@ namespace Avalonia.MonoMac } } + public Action WindowStateChanged { get; set; } + bool IsZoomed => IsDecorated ? Window.IsZoomed : UndecoratedIsMaximized; public bool UndecoratedIsMaximized => Window.Frame == Window.Screen.VisibleFrame; diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index 5c24aa1c69..fef0ef747d 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -104,6 +104,30 @@ namespace Avalonia.Win32.Interop ForceMinimize = 11 } + public enum SysCommands + { + SC_SIZE = 0xF000, + SC_MOVE = 0xF010, + SC_MINIMIZE = 0xF020, + SC_MAXIMIZE = 0xF030, + SC_NEXTWINDOW = 0xF040, + SC_PREVWINDOW = 0xF050, + SC_CLOSE = 0xF060, + SC_VSCROLL = 0xF070, + SC_HSCROLL = 0xF080, + SC_MOUSEMENU = 0xF090, + SC_KEYMENU = 0xF100, + SC_ARRANGE = 0xF110, + SC_RESTORE = 0xF120, + SC_TASKLIST = 0xF130, + SC_SCREENSAVE = 0xF140, + SC_HOTKEY = 0xF150, + SC_DEFAULT = 0xF160, + SC_MONITORPOWER = 0xF170, + SC_CONTEXTHELP = 0xF180, + SC_SEPARATOR = 0xF00F, + } + public enum SystemMetric { SM_CXSCREEN = 0, // 0x00 diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index cf6cb40e58..399a09ea6c 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -77,6 +77,8 @@ namespace Avalonia.Win32 public Action PositionChanged { get; set; } + public Action WindowStateChanged { get; set; } + public Thickness BorderThickness { get @@ -627,6 +629,25 @@ namespace Avalonia.Win32 return IntPtr.Zero; + case UnmanagedMethods.WindowsMessage.WM_SYSCOMMAND: + if (WindowStateChanged != null) + { + switch ((SysCommands)wParam) + { + case SysCommands.SC_MINIMIZE: + WindowStateChanged(WindowState.Minimized); + break; + case SysCommands.SC_MAXIMIZE: + WindowStateChanged(WindowState.Maximized); + break; + case SysCommands.SC_RESTORE: + WindowStateChanged(WindowState.Normal); + break; + } + } + + break; + case UnmanagedMethods.WindowsMessage.WM_MOVE: PositionChanged?.Invoke(new Point((short)(ToInt32(lParam) & 0xffff), (short)(ToInt32(lParam) >> 16))); return IntPtr.Zero;