Browse Source

add hints for further control over chrome.

Dan Walmsley 5 years ago
parent
commit
37e4e68b9d

+ 17 - 0
src/Avalonia.Controls/Platform/ExtendClientAreaChromeHints.cs

@@ -0,0 +1,17 @@
+using System;
+
+namespace Avalonia.Platform
+{
+    [Flags]
+    public enum ExtendClientAreaChromeHints
+    {        
+        Default = SystemTitleBar | SystemChromeButtons,
+        NoChrome,
+        SystemTitleBar = 0x01,
+        SystemChromeButtons = 0x02,
+        ManagedChromeButtons = 0x04,
+        PreferSystemChromeButtons = 0x08,
+        AdaptiveChromeWithTitleBar = SystemTitleBar | PreferSystemChromeButtons,
+        AdaptiveChromeWithoutTitleBar = PreferSystemChromeButtons,
+    }
+}

+ 5 - 1
src/Avalonia.Controls/Platform/IWindowImpl.cs

@@ -95,7 +95,11 @@ namespace Avalonia.Platform
         /// 
         void SetMinMaxSize(Size minSize, Size maxSize);
 
-        bool ExtendClientAreaToDecorationsHint { get; set; }
+        void SetExtendClientAreaToDecorationsHint(bool extendIntoClientAreaHint);
+
+        bool IsClientAreaExtendedToDecorations { get; }
+
+        void SetExtendClientAreaChromeHints(ExtendClientAreaChromeHints hints);
 
         Action<bool> ExtendClientAreaToDecorationsChanged { get; set; }
         

+ 13 - 1
src/Avalonia.Controls/Window.cs

@@ -95,6 +95,9 @@ namespace Avalonia.Controls
         public static readonly StyledProperty<bool> ExtendClientAreaToDecorationsHintProperty =
             AvaloniaProperty.Register<Window, bool>(nameof(ExtendClientAreaToDecorationsHint), false);
 
+        public static readonly StyledProperty<ExtendClientAreaChromeHints> ExtendClientAreaChromeHintsProperty =
+            AvaloniaProperty.Register<Window, ExtendClientAreaChromeHints>(nameof(ExtendClientAreaChromeHints), ExtendClientAreaChromeHints.Default);
+
 
         /// <summary>
         /// Defines the <see cref="IsExtendedIntoWindowDecorations"/> property.
@@ -190,7 +193,10 @@ namespace Avalonia.Controls
                 (w, e) => { if (w.PlatformImpl != null) w.PlatformImpl.WindowState = (WindowState)e.NewValue; });
 
             ExtendClientAreaToDecorationsHintProperty.Changed.AddClassHandler<Window>(
-                (w, e) => { if (w.PlatformImpl != null) w.PlatformImpl.ExtendClientAreaToDecorationsHint = (bool)e.NewValue; });
+                (w, e) => { if (w.PlatformImpl != null) w.PlatformImpl.SetExtendClientAreaToDecorationsHint((bool)e.NewValue); });
+
+            ExtendClientAreaChromeHintsProperty.Changed.AddClassHandler<Window>(
+                (w, e) => { if (w.PlatformImpl != null) w.PlatformImpl.SetExtendClientAreaChromeHints((ExtendClientAreaChromeHints)e.NewValue); });
 
             MinWidthProperty.Changed.AddClassHandler<Window>((w, e) => w.PlatformImpl?.SetMinMaxSize(new Size((double)e.NewValue, w.MinHeight), new Size(w.MaxWidth, w.MaxHeight)));
             MinHeightProperty.Changed.AddClassHandler<Window>((w, e) => w.PlatformImpl?.SetMinMaxSize(new Size(w.MinWidth, (double)e.NewValue), new Size(w.MaxWidth, w.MaxHeight)));
@@ -275,6 +281,12 @@ namespace Avalonia.Controls
             set { SetValue(ExtendClientAreaToDecorationsHintProperty, value); }
         }
 
+        public ExtendClientAreaChromeHints ExtendClientAreaChromeHints
+        {
+            get => GetValue(ExtendClientAreaChromeHintsProperty);
+            set => SetValue(ExtendClientAreaChromeHintsProperty, value);
+        }
+
         /// <summary>
         /// Gets if the ClientArea is Extended into the Window Decorations.
         /// </summary>

+ 11 - 3
src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs

@@ -83,14 +83,14 @@ namespace Avalonia.DesignerSupport.Remote
         }
 
         public IScreenImpl Screen { get; } = new ScreenStub();
-        public Action GotInputWhenDisabled { get; set; }
-        
-        public bool ExtendClientAreaToDecorationsHint { get; set; }
+        public Action GotInputWhenDisabled { get; set; }        
         
         public Action<bool> ExtendClientAreaToDecorationsChanged { get; set; }
 
         public Thickness ExtendedMargins { get; } = new Thickness();
 
+        public bool IsClientAreaExtendedToDecorations { get; }
+
         public void Activate()
         {
         }
@@ -130,5 +130,13 @@ namespace Avalonia.DesignerSupport.Remote
         public void SetEnabled(bool enable)
         {
         }
+
+        public void SetExtendClientAreaToDecorationsHint(bool extendIntoClientAreaHint)
+        {            
+        }
+
+        public void SetExtendClientAreaChromeHints(ExtendClientAreaChromeHints hints)
+        {            
+        }
     }
 }

+ 11 - 3
src/Avalonia.DesignerSupport/Remote/Stubs.cs

@@ -37,9 +37,7 @@ namespace Avalonia.DesignerSupport.Remote
         public WindowState WindowState { get; set; }
         public Action<WindowState> WindowStateChanged { get; set; }
 
-        public Action<WindowTransparencyLevel> TransparencyLevelChanged { get; set; }
-
-        public bool ExtendClientAreaToDecorationsHint { get; set; }
+        public Action<WindowTransparencyLevel> TransparencyLevelChanged { get; set; }        
 
         public Action<bool> ExtendClientAreaToDecorationsChanged { get; set; }
 
@@ -146,6 +144,14 @@ namespace Avalonia.DesignerSupport.Remote
         {
         }
 
+        public void SetExtendClientAreaToDecorationsHint(bool extendIntoClientAreaHint)
+        {
+        }
+
+        public void SetExtendClientAreaChromeHints(ExtendClientAreaChromeHints hints)
+        {
+        }
+
         public IPopupPositioner PopupPositioner { get; }
 
         public Action GotInputWhenDisabled { get; set; }
@@ -157,6 +163,8 @@ namespace Avalonia.DesignerSupport.Remote
         }
 
         public WindowTransparencyLevel TransparencyLevel { get; private set; }
+
+        public bool IsClientAreaExtendedToDecorations { get; }
     }
 
     class ClipboardStub : IClipboard

+ 11 - 3
src/Avalonia.Native/WindowImpl.cs

@@ -96,14 +96,22 @@ namespace Avalonia.Native
             }
         }
 
-        public Action<WindowState> WindowStateChanged { get; set; }
-
-        public bool ExtendClientAreaToDecorationsHint { get; set; }
+        public Action<WindowState> WindowStateChanged { get; set; }        
 
         public Action<bool> ExtendClientAreaToDecorationsChanged { get; set; }
 
         public Thickness ExtendedMargins { get; } = new Thickness();
 
+        public bool IsClientAreaExtendedToDecorations { get; }
+
+        public void SetExtendClientAreaToDecorationsHint(bool extendIntoClientAreaHint)
+        {
+        }
+
+        public void SetExtendClientAreaChromeHints(ExtendClientAreaChromeHints hints)
+        {
+        }
+
         public void ShowTaskbarIcon(bool value)
         {
             // NO OP On OSX

+ 11 - 3
src/Avalonia.X11/X11Window.cs

@@ -309,14 +309,14 @@ namespace Avalonia.X11
         {
             get => _transparencyHelper.TransparencyLevelChanged;
             set => _transparencyHelper.TransparencyLevelChanged = value;
-        }
-
-        public bool ExtendClientAreaToDecorationsHint { get; set; }
+        }        
 
         public Action<bool> ExtendClientAreaToDecorationsChanged { get; set; }
 
         public Thickness ExtendedMargins { get; } = new Thickness();
 
+        public bool IsClientAreaExtendedToDecorations { get; }
+
         public Action Closed { get; set; }
         public Action<PixelPoint> PositionChanged { get; set; }
 
@@ -1041,6 +1041,14 @@ namespace Avalonia.X11
             _disabled = !enable;
         }
 
+        public void SetExtendClientAreaToDecorationsHint(bool extendIntoClientAreaHint)
+        {
+        }
+
+        public void SetExtendClientAreaChromeHints(ExtendClientAreaChromeHints hints)
+        {
+        }
+
         public Action GotInputWhenDisabled { get; set; }
 
         public void SetIcon(IWindowIconImpl icon)

+ 6 - 0
src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs

@@ -989,6 +989,12 @@ namespace Avalonia.Win32.Interop
             }
         }
 
+        [DllImport("user32.dll")]
+        public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
+
+        [DllImport("user32.dll")]
+        public static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);
+
         [DllImport("user32.dll", SetLastError = true)]
         public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
 

+ 59 - 15
src/Windows/Avalonia.Win32/WindowImpl.cs

@@ -41,6 +41,7 @@ namespace Avalonia.Win32
         private SavedWindowInfo _savedWindowInfo;
         private bool _isFullScreenActive;
         private bool _isClientAreaExtended;
+        private Thickness _extendedMargins;
 
 #if USE_MANAGED_DRAG
         private readonly ManagedWindowResizeDragHelper _managedDrag;
@@ -666,7 +667,7 @@ namespace Avalonia.Win32
             TaskBarList.MarkFullscreen(_hwnd, fullscreen);
         }
 
-        private void ExtendClientArea ()
+        private void ExtendClientArea (ExtendClientAreaChromeHints hints)
         {
             if (!_isClientAreaExtended)
             {
@@ -683,6 +684,16 @@ namespace Avalonia.Win32
                     AdjustWindowRectEx(ref border_thickness, (uint)(GetStyle()), false, 0);
                     border_thickness.left *= -1;
                     border_thickness.top *= -1;
+
+                    border_thickness.left = 1;
+                    border_thickness.bottom = 1;
+                    border_thickness.right = 1;                                        
+
+                    if (!hints.HasFlag(ExtendClientAreaChromeHints.SystemTitleBar))
+                    {
+                        border_thickness.top = 1;
+                    }
+
                 }
                 else if (GetStyle().HasFlag(WindowStyles.WS_BORDER))
                 {
@@ -697,6 +708,19 @@ namespace Avalonia.Win32
 
                 var hr = DwmExtendFrameIntoClientArea(_hwnd, ref margins);
 
+                if(!hints.HasFlag(ExtendClientAreaChromeHints.SystemChromeButtons) ||
+                    (hints.HasFlag(ExtendClientAreaChromeHints.PreferSystemChromeButtons) &&
+                    !hints.HasFlag(ExtendClientAreaChromeHints.SystemTitleBar)))
+                {
+                    var style = GetStyle();
+
+                    style &= ~(WindowStyles.WS_MINIMIZEBOX | WindowStyles.WS_MAXIMIZEBOX | WindowStyles.WS_SYSMENU);
+
+                    SetStyle(style);
+
+                    DisableCloseButton(_hwnd);
+                }
+
                 if (hr == 0)
                 {
                     _isClientAreaExtended = true;
@@ -854,9 +878,10 @@ namespace Avalonia.Win32
                 // Otherwise it will still show in the taskbar.
             }
 
+            WindowStyles style;
             if ((oldProperties.IsResizable != newProperties.IsResizable) || forceChanges)
             {
-                var style = GetStyle();
+                style = GetStyle();
 
                 if (newProperties.IsResizable)
                 {
@@ -877,7 +902,7 @@ namespace Avalonia.Win32
 
             if ((oldProperties.Decorations != newProperties.Decorations) || forceChanges)
             {
-                var style = GetStyle();
+                style = GetStyle();
 
                 const WindowStyles fullDecorationFlags = WindowStyles.WS_CAPTION | WindowStyles.WS_SYSMENU;
 
@@ -922,7 +947,26 @@ namespace Avalonia.Win32
                         SetWindowPosFlags.SWP_NOZORDER | SetWindowPosFlags.SWP_NOACTIVATE |
                         SetWindowPosFlags.SWP_FRAMECHANGED);
                 }
-            }
+            }            
+        }
+
+        private const int MF_BYCOMMAND = 0x0;
+        private const int MF_BYPOSITION = 0x400;
+        private const int MF_REMOVE = 0x1000;
+        private const int MF_ENABLED = 0x0;
+        private const int MF_GRAYED = 0x1;
+        private const int MF_DISABLED = 0x2;
+        private const int SC_CLOSE = 0xF060;
+
+        void DisableCloseButton(IntPtr hwnd)
+        {
+            EnableMenuItem(GetSystemMenu(hwnd, false), SC_CLOSE,
+                           MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+        }
+        void EnableCloseButton(IntPtr hwnd)
+        {
+            EnableMenuItem(GetSystemMenu(hwnd, false), SC_CLOSE,
+                           MF_BYCOMMAND | MF_ENABLED);
         }
 
 #if USE_MANAGED_DRAG
@@ -946,23 +990,23 @@ namespace Avalonia.Win32
             }
         }
 
-        IntPtr EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Handle => Handle.Handle;        
+        IntPtr EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Handle => Handle.Handle;
 
-        public bool ExtendClientAreaToDecorationsHint
+        public void SetExtendClientAreaToDecorationsHint(bool hint)
         {
-            get => _extendClientAreaToDecorationsHint;
-            set
-            {
-                _extendClientAreaToDecorationsHint = true;
+            ExtendClientArea(_extendChromeHints);
+        }
 
-                ExtendClientArea();
-                // TODO Trigger transition.
-            }
+        private ExtendClientAreaChromeHints _extendChromeHints = ExtendClientAreaChromeHints.Default;
+
+        public void SetExtendClientAreaChromeHints(ExtendClientAreaChromeHints hints)
+        {
+            _extendChromeHints = hints;
         }
 
-        public Action<bool> ExtendClientAreaToDecorationsChanged { get; set; }
+        public bool IsClientAreaExtendedToDecorations => _isClientAreaExtended;
 
-        private Thickness _extendedMargins;
+        public Action<bool> ExtendClientAreaToDecorationsChanged { get; set; }        
 
         public Thickness ExtendedMargins => _extendedMargins;