Browse Source

Merge branch 'master' into feature/textbox-selectedtext

pull/3658/head
Steven Kirk 7 years ago
committed by GitHub
parent
commit
2bd9372170
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      native/Avalonia.Native/inc/avalonia-native.h
  2. 81
      native/Avalonia.Native/src/OSX/window.mm
  3. 11
      samples/ControlCatalog/MainView.xaml
  4. 14
      samples/ControlCatalog/MainView.xaml.cs
  5. 6
      src/Avalonia.Base/AvaloniaObject.cs
  6. 88
      src/Avalonia.Base/AvaloniaPropertyRegistry.cs
  7. 2
      src/Avalonia.Controls/Platform/IWindowImpl.cs
  8. 25
      src/Avalonia.Controls/TextBox.cs
  9. 96
      src/Avalonia.Controls/Window.cs
  10. 2
      src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs
  11. 2
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  12. 4
      src/Avalonia.Native/WindowImpl.cs
  13. 16
      src/Avalonia.X11/X11Window.cs
  14. 10
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  15. 20
      src/Windows/Avalonia.Win32/WindowImpl.cs
  16. 2
      src/iOS/Avalonia.iOS/EmbeddableImpl.cs

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

@ -25,6 +25,12 @@ struct IAvnGlSurfaceRenderingSession;
struct IAvnAppMenu;
struct IAvnAppMenuItem;
enum SystemDecorations {
SystemDecorationsNone = 0,
SystemDecorationsBorderOnly = 1,
SystemDecorationsFull = 2,
};
struct AvnSize
{
double Width, Height;
@ -236,7 +242,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(SystemDecorations value) = 0;
virtual HRESULT SetTitle (void* utf8Title) = 0;
virtual HRESULT SetTitleBarColor (AvnColor color) = 0;
virtual HRESULT SetWindowState(AvnWindowState state) = 0;

81
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;
SystemDecorations _hasDecorations = SystemDecorationsFull;
CGRect _lastUndecoratedFrame;
AvnWindowState _lastWindowState;
@ -476,23 +475,26 @@ private:
bool IsZoomed ()
{
return _hasDecorations ? [Window isZoomed] : UndecoratedIsMaximized();
return _hasDecorations != SystemDecorationsNone ? [Window isZoomed] : UndecoratedIsMaximized();
}
void DoZoom()
{
if (_hasDecorations)
switch (_hasDecorations)
{
[Window performZoom:Window];
}
else
{
if (!UndecoratedIsMaximized())
{
_lastUndecoratedFrame = [Window frame];
}
[Window zoom:Window];
case SystemDecorationsNone:
if (!UndecoratedIsMaximized())
{
_lastUndecoratedFrame = [Window frame];
}
[Window zoom:Window];
break;
case SystemDecorationsBorderOnly:
case SystemDecorationsFull:
[Window performZoom:Window];
break;
}
}
@ -506,13 +508,35 @@ private:
}
}
virtual HRESULT SetHasDecorations(bool value) override
virtual HRESULT SetHasDecorations(SystemDecorations value) override
{
@autoreleasepool
{
_hasDecorations = value;
UpdateStyle();
switch (_hasDecorations)
{
case SystemDecorationsNone:
[Window setHasShadow:NO];
[Window setTitleVisibility:NSWindowTitleHidden];
[Window setTitlebarAppearsTransparent:YES];
break;
case SystemDecorationsBorderOnly:
[Window setHasShadow:YES];
[Window setTitleVisibility:NSWindowTitleHidden];
[Window setTitlebarAppearsTransparent:YES];
break;
case SystemDecorationsFull:
[Window setHasShadow:YES];
[Window setTitleVisibility:NSWindowTitleVisible];
[Window setTitlebarAppearsTransparent:NO];
[Window setTitle:_lastTitle];
break;
}
return S_OK;
}
}
@ -523,7 +547,6 @@ private:
{
_lastTitle = [NSString stringWithUTF8String:(const char*)utf8title];
[Window setTitle:_lastTitle];
[Window setTitleVisibility:NSWindowTitleVisible];
return S_OK;
}
@ -645,10 +668,26 @@ protected:
virtual NSWindowStyleMask GetStyle() override
{
unsigned long s = NSWindowStyleMaskBorderless;
if(_hasDecorations)
s = s | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
if(_canResize)
s = s | NSWindowStyleMaskResizable;
switch (_hasDecorations)
{
case SystemDecorationsNone:
break;
case SystemDecorationsBorderOnly:
s = s | NSWindowStyleMaskTitled | NSWindowStyleMaskFullSizeContentView;
break;
case SystemDecorationsFull:
s = s | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskBorderless;
if(_canResize)
{
s = s | NSWindowStyleMaskResizable;
}
break;
}
return s;
}
};

11
samples/ControlCatalog/MainView.xaml

@ -59,10 +59,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;
}
}
}

6
src/Avalonia.Base/AvaloniaObject.cs

@ -80,8 +80,12 @@ namespace Avalonia
_inheritanceParent?.RemoveInheritanceChild(this);
_inheritanceParent = value;
foreach (var property in AvaloniaPropertyRegistry.Instance.GetRegisteredInherited(GetType()))
var properties = AvaloniaPropertyRegistry.Instance.GetRegisteredInherited(GetType());
var propertiesCount = properties.Count;
for (var i = 0; i < propertiesCount; i++)
{
var property = properties[i];
if (valuestore?.IsSet(property) == true)
{
// If local value set there can be no change.

88
src/Avalonia.Base/AvaloniaPropertyRegistry.cs

@ -3,9 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Avalonia.Data;
namespace Avalonia
{
@ -28,8 +26,6 @@ namespace Avalonia
new Dictionary<Type, List<AvaloniaProperty>>();
private readonly Dictionary<Type, List<AvaloniaProperty>> _directCache =
new Dictionary<Type, List<AvaloniaProperty>>();
private readonly Dictionary<Type, List<PropertyInitializationData>> _initializedCache =
new Dictionary<Type, List<PropertyInitializationData>>();
private readonly Dictionary<Type, List<AvaloniaProperty>> _inheritedCache =
new Dictionary<Type, List<AvaloniaProperty>>();
@ -49,7 +45,7 @@ namespace Avalonia
/// </summary>
/// <param name="type">The type.</param>
/// <returns>A collection of <see cref="AvaloniaProperty"/> definitions.</returns>
public IEnumerable<AvaloniaProperty> GetRegistered(Type type)
public IReadOnlyList<AvaloniaProperty> GetRegistered(Type type)
{
Contract.Requires<ArgumentNullException>(type != null);
@ -83,7 +79,7 @@ namespace Avalonia
/// </summary>
/// <param name="type">The type.</param>
/// <returns>A collection of <see cref="AvaloniaProperty"/> definitions.</returns>
public IEnumerable<AvaloniaProperty> GetRegisteredAttached(Type type)
public IReadOnlyList<AvaloniaProperty> GetRegisteredAttached(Type type)
{
Contract.Requires<ArgumentNullException>(type != null);
@ -114,7 +110,7 @@ namespace Avalonia
/// </summary>
/// <param name="type">The type.</param>
/// <returns>A collection of <see cref="AvaloniaProperty"/> definitions.</returns>
public IEnumerable<AvaloniaProperty> GetRegisteredDirect(Type type)
public IReadOnlyList<AvaloniaProperty> GetRegisteredDirect(Type type)
{
Contract.Requires<ArgumentNullException>(type != null);
@ -145,7 +141,7 @@ namespace Avalonia
/// </summary>
/// <param name="type">The type.</param>
/// <returns>A collection of <see cref="AvaloniaProperty"/> definitions.</returns>
public IEnumerable<AvaloniaProperty> GetRegisteredInherited(Type type)
public IReadOnlyList<AvaloniaProperty> GetRegisteredInherited(Type type)
{
Contract.Requires<ArgumentNullException>(type != null);
@ -157,16 +153,27 @@ namespace Avalonia
result = new List<AvaloniaProperty>();
var visited = new HashSet<AvaloniaProperty>();
foreach (var property in GetRegistered(type))
var registered = GetRegistered(type);
var registeredCount = registered.Count;
for (var i = 0; i < registeredCount; i++)
{
var property = registered[i];
if (property.Inherits)
{
result.Add(property);
visited.Add(property);
}
}
foreach (var property in GetRegisteredAttached(type))
var registeredAttached = GetRegisteredAttached(type);
var registeredAttachedCount = registeredAttached.Count;
for (var i = 0; i < registeredAttachedCount; i++)
{
var property = registeredAttached[i];
if (property.Inherits)
{
if (!visited.Contains(property))
@ -185,7 +192,7 @@ namespace Avalonia
/// </summary>
/// <param name="o">The object.</param>
/// <returns>A collection of <see cref="AvaloniaProperty"/> definitions.</returns>
public IEnumerable<AvaloniaProperty> GetRegistered(IAvaloniaObject o)
public IReadOnlyList<AvaloniaProperty> GetRegistered(IAvaloniaObject o)
{
Contract.Requires<ArgumentNullException>(o != null);
@ -229,8 +236,13 @@ namespace Avalonia
throw new InvalidOperationException("Attached properties not supported.");
}
foreach (AvaloniaProperty x in GetRegistered(type))
var registered = GetRegistered(type);
var registeredCount = registered.Count;
for (var i = 0; i < registeredCount; i++)
{
AvaloniaProperty x = registered[i];
if (x.Name == name)
{
return x;
@ -276,8 +288,13 @@ namespace Avalonia
return property;
}
foreach (var p in GetRegisteredDirect(o.GetType()))
var registeredDirect = GetRegisteredDirect(o.GetType());
var registeredDirectCount = registeredDirect.Count;
for (var i = 0; i < registeredDirectCount; i++)
{
var p = registeredDirect[i];
if (p == property)
{
return (DirectPropertyBase<T>)p;
@ -308,8 +325,23 @@ namespace Avalonia
Contract.Requires<ArgumentNullException>(type != null);
Contract.Requires<ArgumentNullException>(property != null);
return Instance.GetRegistered(type).Any(x => x == property) ||
Instance.GetRegisteredAttached(type).Any(x => x == property);
static bool ContainsProperty(IReadOnlyList<AvaloniaProperty> properties, AvaloniaProperty property)
{
var propertiesCount = properties.Count;
for (var i = 0; i < propertiesCount; i++)
{
if (properties[i] == property)
{
return true;
}
}
return false;
}
return ContainsProperty(Instance.GetRegistered(type), property) ||
ContainsProperty(Instance.GetRegisteredAttached(type), property);
}
/// <summary>
@ -374,7 +406,6 @@ namespace Avalonia
}
_registeredCache.Clear();
_initializedCache.Clear();
_inheritedCache.Clear();
}
@ -411,32 +442,7 @@ namespace Avalonia
}
_attachedCache.Clear();
_initializedCache.Clear();
_inheritedCache.Clear();
}
private readonly struct PropertyInitializationData
{
public AvaloniaProperty Property { get; }
public object Value { get; }
public bool IsDirect { get; }
public IDirectPropertyAccessor DirectAccessor { get; }
public PropertyInitializationData(AvaloniaProperty property, IDirectPropertyAccessor directAccessor)
{
Property = property;
Value = null;
IsDirect = true;
DirectAccessor = directAccessor;
}
public PropertyInitializationData(AvaloniaProperty property, IStyledPropertyAccessor styledAccessor, Type type)
{
Property = property;
Value = styledAccessor.GetDefaultValue(type);
IsDirect = false;
DirectAccessor = null;
}
}
}
}

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.

25
src/Avalonia.Controls/TextBox.cs

@ -699,12 +699,12 @@ namespace Avalonia.Controls
protected override void OnPointerPressed(PointerPressedEventArgs e)
{
var point = e.GetPosition(_presenter);
var index = CaretIndex = _presenter.GetCaretIndex(point);
var text = Text;
if (text != null && e.MouseButton == MouseButton.Left)
if (text != null && e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
{
var point = e.GetPosition(_presenter);
var index = CaretIndex = _presenter.GetCaretIndex(point);
switch (e.ClickCount)
{
case 1:
@ -730,7 +730,8 @@ namespace Avalonia.Controls
protected override void OnPointerMoved(PointerEventArgs e)
{
if (_presenter != null && e.Pointer.Captured == _presenter)
// selection should not change during pointer move if the user right clicks
if (_presenter != null && e.Pointer.Captured == _presenter && e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
{
var point = e.GetPosition(_presenter);
@ -743,6 +744,22 @@ namespace Avalonia.Controls
{
if (_presenter != null && e.Pointer.Captured == _presenter)
{
if (e.InitialPressMouseButton == MouseButton.Right)
{
var point = e.GetPosition(_presenter);
var caretIndex = _presenter.GetCaretIndex(point);
// see if mouse clicked inside current selection
// if it did not, we change the selection to where the user clicked
var firstSelection = Math.Min(SelectionStart, SelectionEnd);
var lastSelection = Math.Max(SelectionStart, SelectionEnd);
var didClickInSelection = SelectionStart != SelectionEnd &&
caretIndex >= firstSelection && caretIndex <= lastSelection;
if (!didClickInSelection)
{
CaretIndex = SelectionEnd = SelectionStart = caretIndex;
}
}
e.Pointer.Capture(null);
}
}

96
src/Avalonia.Controls/Window.cs

@ -2,19 +2,19 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.ComponentModel;
using System.Linq;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Avalonia.Controls.Platform;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Styling;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using System.ComponentModel;
using Avalonia.Interactivity;
namespace Avalonia.Controls
{
@ -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,8 +80,18 @@ namespace Avalonia.Controls
/// <summary>
/// Enables or disables system window decorations (title bar, buttons, etc)
/// </summary>
public static readonly StyledProperty<bool> HasSystemDecorationsProperty =
AvaloniaProperty.Register<Window, bool>(nameof(HasSystemDecorations), true);
[Obsolete("Use SystemDecorationsProperty instead")]
public static readonly DirectProperty<Window, bool> HasSystemDecorationsProperty =
AvaloniaProperty.RegisterDirect<Window, bool>(
nameof(HasSystemDecorations),
o => o.HasSystemDecorations,
(o, v) => o.HasSystemDecorations = v);
/// <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
@ -124,9 +155,6 @@ 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));
ShowInTaskbarProperty.Changed.AddClassHandler<Window>((w, e) => w.PlatformImpl?.ShowTaskbarIcon((bool)e.NewValue));
IconProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl?.SetIcon(((WindowIcon)e.NewValue)?.PlatformImpl));
@ -135,12 +163,11 @@ namespace Avalonia.Controls
WindowStateProperty.Changed.AddClassHandler<Window>(
(w, e) => { if (w.PlatformImpl != null) w.PlatformImpl.WindowState = (WindowState)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)));
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>
@ -191,11 +218,30 @@ namespace Avalonia.Controls
/// <summary>
/// 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); }
get => SystemDecorations == SystemDecorations.Full;
set
{
var oldValue = HasSystemDecorations;
if (oldValue != value)
{
SystemDecorations = value ? SystemDecorations.Full : SystemDecorations.None;
RaisePropertyChanged(HasSystemDecorationsProperty, oldValue, value);
}
}
}
/// <summary>
/// Sets the system decorations (title bar, border, etc)
/// </summary>
///
public SystemDecorations SystemDecorations
{
get { return GetValue(SystemDecorationsProperty); }
set { SetValue(SystemDecorationsProperty, value); }
}
/// <summary>
@ -584,5 +630,27 @@ namespace Avalonia.Controls
/// <see cref="Closing"/> event needs to be raised.
/// </remarks>
protected virtual void OnClosing(CancelEventArgs e) => Closing?.Invoke(this, e);
protected override void OnPropertyChanged<T>(
AvaloniaProperty<T> property,
Optional<T> oldValue,
BindingValue<T> newValue,
BindingPriority priority)
{
if (property == SystemDecorationsProperty)
{
var typedNewValue = newValue.GetValueOrDefault<SystemDecorations>();
PlatformImpl?.SetSystemDecorations(typedNewValue);
var o = oldValue.GetValueOrDefault<SystemDecorations>() == SystemDecorations.Full;
var n = typedNewValue == SystemDecorations.Full;
if (o != n)
{
RaisePropertyChanged(HasSystemDecorationsProperty, o, n);
}
}
}
}
}

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(Controls.SystemDecorations enabled)
{
_native.HasDecorations = enabled;
_native.HasDecorations = (Interop.SystemDecorations)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