Browse Source

Rework system decorations

pull/3539/head
Nathan Garside 7 years ago
parent
commit
7b9d32af85
  1. 2
      native/Avalonia.Native/inc/avalonia-native.h
  2. 41
      native/Avalonia.Native/src/OSX/window.mm
  3. 11
      samples/ControlCatalog/MainView.xaml
  4. 14
      samples/ControlCatalog/MainView.xaml.cs
  5. 2
      src/Avalonia.Controls/Platform/IWindowImpl.cs
  6. 44
      src/Avalonia.Controls/Window.cs
  7. 2
      src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs
  8. 2
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  9. 4
      src/Avalonia.Native/WindowImpl.cs
  10. 16
      src/Avalonia.X11/X11Window.cs
  11. 10
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  12. 20
      src/Windows/Avalonia.Win32/WindowImpl.cs
  13. 2
      src/iOS/Avalonia.iOS/EmbeddableImpl.cs

2
native/Avalonia.Native/inc/avalonia-native.h

@ -236,7 +236,7 @@ AVNCOM(IAvnWindow, 04) : virtual IAvnWindowBase
{
virtual HRESULT ShowDialog (IAvnWindow* parent) = 0;
virtual HRESULT SetCanResize(bool value) = 0;
virtual HRESULT SetHasDecorations(bool value) = 0;
virtual HRESULT SetHasDecorations(int value) = 0;
virtual HRESULT SetTitle (void* utf8Title) = 0;
virtual HRESULT SetTitleBarColor (AvnColor color) = 0;
virtual HRESULT SetWindowState(AvnWindowState state) = 0;

41
native/Avalonia.Native/src/OSX/window.mm

@ -115,7 +115,6 @@ public:
[NSApp activateIgnoringOtherApps:YES];
[Window setTitle:_lastTitle];
[Window setTitleVisibility:NSWindowTitleVisible];
return S_OK;
}
@ -411,7 +410,7 @@ class WindowImpl : public virtual WindowBaseImpl, public virtual IAvnWindow, pub
{
private:
bool _canResize = true;
bool _hasDecorations = true;
int _hasDecorations = 2;
CGRect _lastUndecoratedFrame;
AvnWindowState _lastWindowState;
@ -476,12 +475,12 @@ private:
bool IsZoomed ()
{
return _hasDecorations ? [Window isZoomed] : UndecoratedIsMaximized();
return _hasDecorations > 0 ? [Window isZoomed] : UndecoratedIsMaximized();
}
void DoZoom()
{
if (_hasDecorations)
if (_hasDecorations > 0)
{
[Window performZoom:Window];
}
@ -506,13 +505,36 @@ private:
}
}
virtual HRESULT SetHasDecorations(bool value) override
virtual HRESULT SetHasDecorations(int value) override
{
@autoreleasepool
{
_hasDecorations = value;
UpdateStyle();
// full
if (_hasDecorations == 2)
{
[Window setHasShadow:YES];
[Window setTitleVisibility:NSWindowTitleVisible];
[Window setTitlebarAppearsTransparent:NO];
[Window setTitle:_lastTitle];
}
// border only
else if (_hasDecorations == 1)
{
[Window setHasShadow:YES];
[Window setTitleVisibility:NSWindowTitleHidden];
[Window setTitlebarAppearsTransparent:YES];
}
// none
else
{
[Window setHasShadow:NO];
[Window setTitleVisibility:NSWindowTitleHidden];
[Window setTitlebarAppearsTransparent:YES];
}
return S_OK;
}
}
@ -523,7 +545,6 @@ private:
{
_lastTitle = [NSString stringWithUTF8String:(const char*)utf8title];
[Window setTitle:_lastTitle];
[Window setTitleVisibility:NSWindowTitleVisible];
return S_OK;
}
@ -645,9 +666,11 @@ protected:
virtual NSWindowStyleMask GetStyle() override
{
unsigned long s = NSWindowStyleMaskBorderless;
if(_hasDecorations)
s = s | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
if(_canResize)
if(_hasDecorations == 1)
s = s | NSWindowStyleMaskTitled | NSWindowStyleMaskFullSizeContentView;
if(_hasDecorations == 2)
s = s | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskBorderless;
if(_hasDecorations == 2 && _canResize)
s = s | NSWindowStyleMaskResizable;
return s;
}

11
samples/ControlCatalog/MainView.xaml

@ -58,10 +58,17 @@
<TabItem Header="TreeView"><pages:TreeViewPage/></TabItem>
<TabItem Header="Viewbox"><pages:ViewboxPage/></TabItem>
<TabControl.Tag>
<ComboBox x:Name="Themes" SelectedIndex="0" Width="100" Margin="8" HorizontalAlignment="Right" VerticalAlignment="Bottom">
<StackPanel Width="115" Margin="8" HorizontalAlignment="Right" VerticalAlignment="Bottom">
<ComboBox x:Name="Decorations" SelectedIndex="0" Margin="0,0,0,8">
<ComboBoxItem>No Decorations</ComboBoxItem>
<ComboBoxItem>Border Only</ComboBoxItem>
<ComboBoxItem>Full Decorations</ComboBoxItem>
</ComboBox>
<ComboBox x:Name="Themes" SelectedIndex="0">
<ComboBoxItem>Light</ComboBoxItem>
<ComboBoxItem>Dark</ComboBoxItem>
</ComboBox>
</ComboBox>
</StackPanel>
</TabControl.Tag>
</TabControl>
</Grid>

14
samples/ControlCatalog/MainView.xaml.cs

@ -56,6 +56,20 @@ namespace ControlCatalog
}
};
Styles.Add(light);
var decorations = this.Find<ComboBox>("Decorations");
decorations.SelectionChanged += (sender, e) =>
{
Window window = (Window)VisualRoot;
window.SystemDecorations = (SystemDecorations)decorations.SelectedIndex;
};
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
var decorations = this.Find<ComboBox>("Decorations");
decorations.SelectedIndex = (int)((Window)VisualRoot).SystemDecorations;
}
}
}

2
src/Avalonia.Controls/Platform/IWindowImpl.cs

@ -36,7 +36,7 @@ namespace Avalonia.Platform
/// <summary>
/// Enables or disables system window decorations (title bar, buttons, etc)
/// </summary>
void SetSystemDecorations(bool enabled);
void SetSystemDecorations(SystemDecorations enabled);
/// <summary>
/// Sets the icon of this window.

44
src/Avalonia.Controls/Window.cs

@ -45,6 +45,27 @@ namespace Avalonia.Controls
WidthAndHeight = 3,
}
/// <summary>
/// Determines system decorations (title bar, border, etc) for a <see cref="Window"/>
/// </summary>
public enum SystemDecorations
{
/// <summary>
/// No decorations
/// </summary>
None = 0,
/// <summary>
/// Window border without titlebar
/// </summary>
BorderOnly = 1,
/// <summary>
/// Fully decorated (default)
/// </summary>
Full = 2
}
/// <summary>
/// A top-level window.
/// </summary>
@ -59,9 +80,16 @@ namespace Avalonia.Controls
/// <summary>
/// Enables or disables system window decorations (title bar, buttons, etc)
/// </summary>
[Obsolete("Use SystemDecorationsProperty instead")]
public static readonly StyledProperty<bool> HasSystemDecorationsProperty =
AvaloniaProperty.Register<Window, bool>(nameof(HasSystemDecorations), true);
/// <summary>
/// Defines the <see cref="SystemDecorations"/> property.
/// </summary>
public static readonly StyledProperty<SystemDecorations> SystemDecorationsProperty =
AvaloniaProperty.Register<Window, SystemDecorations>(nameof(SystemDecorations), SystemDecorations.Full);
/// <summary>
/// Enables or disables the taskbar icon
/// </summary>
@ -125,7 +153,9 @@ namespace Avalonia.Controls
BackgroundProperty.OverrideDefaultValue(typeof(Window), Brushes.White);
TitleProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl?.SetTitle((string)e.NewValue));
HasSystemDecorationsProperty.Changed.AddClassHandler<Window>(
(s, e) => s.PlatformImpl?.SetSystemDecorations((bool)e.NewValue));
(s, e) => s.PlatformImpl?.SetSystemDecorations(((bool)e.NewValue) ? SystemDecorations.Full : SystemDecorations.None));
SystemDecorationsProperty.Changed.AddClassHandler<Window>(
(s, e) => s.PlatformImpl?.SetSystemDecorations((SystemDecorations)e.NewValue));
ShowInTaskbarProperty.Changed.AddClassHandler<Window>((w, e) => w.PlatformImpl?.ShowTaskbarIcon((bool)e.NewValue));
@ -140,7 +170,6 @@ namespace Avalonia.Controls
MinHeightProperty.Changed.AddClassHandler<Window>((w, e) => w.PlatformImpl?.SetMinMaxSize(new Size(w.MinWidth, (double)e.NewValue), new Size(w.MaxWidth, w.MaxHeight)));
MaxWidthProperty.Changed.AddClassHandler<Window>((w, e) => w.PlatformImpl?.SetMinMaxSize(new Size(w.MinWidth, w.MinHeight), new Size((double)e.NewValue, w.MaxHeight)));
MaxHeightProperty.Changed.AddClassHandler<Window>((w, e) => w.PlatformImpl?.SetMinMaxSize(new Size(w.MinWidth, w.MinHeight), new Size(w.MaxWidth, (double)e.NewValue)));
}
/// <summary>
@ -192,12 +221,23 @@ namespace Avalonia.Controls
/// Enables or disables system window decorations (title bar, buttons, etc)
/// </summary>
///
[Obsolete("Use SystemDecorations instead")]
public bool HasSystemDecorations
{
get { return GetValue(HasSystemDecorationsProperty); }
set { SetValue(HasSystemDecorationsProperty, value); }
}
/// <summary>
/// Sets the system decorations (title bar, border, etc)
/// </summary>
///
public SystemDecorations SystemDecorations
{
get { return GetValue(SystemDecorationsProperty); }
set { SetValue(SystemDecorationsProperty, value); }
}
/// <summary>
/// Enables or disables the taskbar icon
/// </summary>

2
src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs

@ -96,7 +96,7 @@ namespace Avalonia.DesignerSupport.Remote
{
}
public void SetSystemDecorations(bool enabled)
public void SetSystemDecorations(SystemDecorations enabled)
{
}

2
src/Avalonia.DesignerSupport/Remote/Stubs.cs

@ -110,7 +110,7 @@ namespace Avalonia.DesignerSupport.Remote
{
}
public void SetSystemDecorations(bool enabled)
public void SetSystemDecorations(SystemDecorations enabled)
{
}

4
src/Avalonia.Native/WindowImpl.cs

@ -68,9 +68,9 @@ namespace Avalonia.Native
_native.CanResize = value;
}
public void SetSystemDecorations(bool enabled)
public void SetSystemDecorations(SystemDecorations enabled)
{
_native.HasDecorations = enabled;
_native.HasDecorations = (int)enabled;
}
public void SetTitleBarColor (Avalonia.Media.Color color)

16
src/Avalonia.X11/X11Window.cs

@ -173,6 +173,7 @@ namespace Avalonia.X11
Surfaces = surfaces.ToArray();
UpdateMotifHints();
UpdateSizeHints(null);
_xic = XCreateIC(_x11.Xim, XNames.XNInputStyle, XIMProperties.XIMPreeditNothing | XIMProperties.XIMStatusNothing,
XNames.XNClientWindow, _handle, IntPtr.Zero);
XFlush(_x11.Display);
@ -219,12 +220,16 @@ namespace Avalonia.X11
var decorations = MotifDecorations.Menu | MotifDecorations.Title | MotifDecorations.Border |
MotifDecorations.Maximize | MotifDecorations.Minimize | MotifDecorations.ResizeH;
if (_popup || !_systemDecorations)
if (_popup || _systemDecorations == SystemDecorations.None)
{
decorations = 0;
}
else if (_systemDecorations == SystemDecorations.BorderOnly)
{
decorations = MotifDecorations.Border;
}
if (!_canResize)
if (!_canResize || _systemDecorations == SystemDecorations.BorderOnly)
{
functions &= ~(MotifFunctions.Resize | MotifFunctions.Maximize);
decorations &= ~(MotifDecorations.Maximize | MotifDecorations.ResizeH);
@ -247,7 +252,7 @@ namespace Avalonia.X11
var min = _minMaxSize.minSize;
var max = _minMaxSize.maxSize;
if (!_canResize)
if (!_canResize || _systemDecorations == SystemDecorations.BorderOnly)
max = min = _realSize;
if (preResize.HasValue)
@ -621,7 +626,7 @@ namespace Avalonia.X11
return rv;
}
private bool _systemDecorations = true;
private SystemDecorations _systemDecorations = SystemDecorations.Full;
private bool _canResize = true;
private const int MaxWindowDimension = 100000;
@ -777,10 +782,11 @@ namespace Avalonia.X11
(int)(point.X * Scaling + Position.X),
(int)(point.Y * Scaling + Position.Y));
public void SetSystemDecorations(bool enabled)
public void SetSystemDecorations(SystemDecorations enabled)
{
_systemDecorations = enabled;
UpdateMotifHints();
UpdateSizeHints(null);
}

10
src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs

@ -1298,7 +1298,17 @@ namespace Avalonia.Win32.Interop
[DllImport("ole32.dll", CharSet = CharSet.Auto, ExactSpelling = true, PreserveSig = false)]
internal static extern void DoDragDrop(IOleDataObject dataObject, IDropSource dropSource, int allowedEffects, out int finalEffect);
[DllImport("dwmapi.dll")]
public static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins);
[StructLayout(LayoutKind.Sequential)]
internal struct MARGINS
{
public int cxLeftWidth;
public int cxRightWidth;
public int cyTopHeight;
public int cyBottomHeight;
}
public enum MONITOR
{

20
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -34,7 +34,7 @@ namespace Avalonia.Win32
private IInputRoot _owner;
private ManagedDeferredRendererLock _rendererLock = new ManagedDeferredRendererLock();
private bool _trackingMouse;
private bool _decorated = true;
private SystemDecorations _decorated = SystemDecorations.Full;
private bool _resizable = true;
private bool _topmost = false;
private bool _taskbarIcon = true;
@ -97,7 +97,7 @@ namespace Avalonia.Win32
{
get
{
if (_decorated)
if (_decorated == SystemDecorations.Full)
{
var style = UnmanagedMethods.GetWindowLong(_hwnd, (int)UnmanagedMethods.WindowLongParam.GWL_STYLE);
var exStyle = UnmanagedMethods.GetWindowLong(_hwnd, (int)UnmanagedMethods.WindowLongParam.GWL_EXSTYLE);
@ -281,7 +281,7 @@ namespace Avalonia.Win32
UnmanagedMethods.ShowWindow(_hwnd, UnmanagedMethods.ShowWindowCommand.Hide);
}
public void SetSystemDecorations(bool value)
public void SetSystemDecorations(SystemDecorations value)
{
if (value == _decorated)
{
@ -464,7 +464,7 @@ namespace Avalonia.Win32
return IntPtr.Zero;
case WindowsMessage.WM_NCCALCSIZE:
if (ToInt32(wParam) == 1 && !_decorated)
if (ToInt32(wParam) == 1 && _decorated != SystemDecorations.Full)
{
return IntPtr.Zero;
}
@ -682,14 +682,14 @@ namespace Avalonia.Win32
break;
case WindowsMessage.WM_NCPAINT:
if (!_decorated)
if (_decorated != SystemDecorations.Full)
{
return IntPtr.Zero;
}
break;
case WindowsMessage.WM_NCACTIVATE:
if (!_decorated)
if (_decorated != SystemDecorations.Full)
{
return new IntPtr(1);
}
@ -1001,7 +1001,7 @@ namespace Avalonia.Win32
style |= WindowStyles.WS_OVERLAPPEDWINDOW;
if (!_decorated)
if (_decorated != SystemDecorations.Full)
{
style ^= (WindowStyles.WS_CAPTION | WindowStyles.WS_SYSMENU);
}
@ -1011,6 +1011,10 @@ namespace Avalonia.Win32
style ^= (WindowStyles.WS_SIZEFRAME);
}
MARGINS margins = new MARGINS();
margins.cyBottomHeight = _decorated == SystemDecorations.BorderOnly ? 1 : 0;
UnmanagedMethods.DwmExtendFrameIntoClientArea(_hwnd, ref margins);
GetClientRect(_hwnd, out var oldClientRect);
var oldClientRectOrigin = new UnmanagedMethods.POINT();
ClientToScreen(_hwnd, ref oldClientRectOrigin);
@ -1024,7 +1028,7 @@ namespace Avalonia.Win32
if (oldDecorated != _decorated)
{
var newRect = oldClientRect;
if (_decorated)
if (_decorated == SystemDecorations.Full)
AdjustWindowRectEx(ref newRect, (uint)style, false,
GetWindowLong(_hwnd, (int)WindowLongParam.GWL_EXSTYLE));
SetWindowPos(_hwnd, IntPtr.Zero, newRect.left, newRect.top, newRect.Width, newRect.Height,

2
src/iOS/Avalonia.iOS/EmbeddableImpl.cs

@ -20,7 +20,7 @@ namespace Avalonia.iOS
return Disposable.Empty;
}
public void SetSystemDecorations(bool enabled)
public void SetSystemDecorations(SystemDecorations enabled)
{
}

Loading…
Cancel
Save