Skip to content

Commit

Permalink
Mac: Fix some issues with AutoSize
Browse files Browse the repository at this point in the history
- Don't enable AutoSize automatically, it should only be enabled by the caller
- Prevent infinite recursion when autosizing
  • Loading branch information
cwensley committed Apr 28, 2021
1 parent cee0098 commit 064e8e9
Showing 1 changed file with 72 additions and 37 deletions.
109 changes: 72 additions & 37 deletions src/Eto.Mac/Forms/MacWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ static class MacWindow
internal static readonly IntPtr selMakeKeyWindow_Handle = Selector.GetHandle("makeKeyWindow");
internal static readonly IntPtr selIsVisible_Handle = Selector.GetHandle("isVisible");
internal static readonly object AnimateSizeChanges_Key = new object();
internal static readonly object DisableAutoSize_Key = new object();
}

public abstract class MacWindow<TControl, TWidget, TCallback> : MacPanel<TControl, TWidget, TCallback>, Window.IHandler, IMacWindow
Expand All @@ -238,7 +239,7 @@ public abstract class MacWindow<TControl, TWidget, TCallback> : MacPanel<TContro
Icon icon;
Eto.Forms.ToolBar toolBar;
Rectangle? restoreBounds;
bool setInitialSize;
bool setInitialSize = true;
WindowState? initialState;
bool maximizable = true;
Point? oldLocation;
Expand Down Expand Up @@ -650,27 +651,39 @@ public override Size Size
}
set
{
var oldFrame = Control.Frame;
var newFrame = oldFrame;
if (value.Width >= 0)
newFrame.Width = value.Width;
if (value.Height > 0)
UserPreferredSize = value;
if (PreferredClientSize != null)
{
newFrame.Height = value.Height;
newFrame.Y = (nfloat)Math.Max(0, oldFrame.Y - (value.Height - oldFrame.Height));
if (value.Width != -1 && value.Height != -1)
PreferredClientSize = new Size(-1, -1);
else if (value.Width != -1)
PreferredClientSize = new Size(-1, PreferredClientSize.Value.Height);
else if (value.Height != -1)
PreferredClientSize = new Size(PreferredClientSize.Value.Width, -1);
}
if (!SetAutoSize())
{
var oldFrame = Control.Frame;
var newFrame = oldFrame;
if (value.Width >= 0)
newFrame.Width = value.Width;
if (value.Height > 0)
{
newFrame.Height = value.Height;
newFrame.Y = (nfloat)Math.Max(0, oldFrame.Y - (value.Height - oldFrame.Height));
}
Control.SetFrame(newFrame, true, AnimateSizeChanges);

}
Control.SetFrame(newFrame, true, AnimateSizeChanges);
UserPreferredSize = value;
SetAutoSize();
}
}

public virtual bool AutoSize
{
get { return Widget.Properties.Get<bool>(MacView.AutoSize_Key, true); }
get { return Widget.Properties.Get<bool>(MacView.AutoSize_Key); }
set
{
if (Widget.Properties.TrySet(MacView.AutoSize_Key, value, true))
if (Widget.Properties.TrySet(MacView.AutoSize_Key, value))
{
if (Widget.Loaded && value)
{
Expand All @@ -680,23 +693,34 @@ public virtual bool AutoSize
}
}

protected void SetAutoSize()
protected bool SetAutoSize()
{
var userPreferredSize = UserPreferredSize;
AutoSize = userPreferredSize.Width == -1 || userPreferredSize.Height == -1;
if (PreferredClientSize != null)
AutoSize &= PreferredClientSize.Value.Width == -1 || PreferredClientSize.Value.Height == -1;
if (AutoSize && Widget.Loaded)
{
var preferredClientSize = PreferredClientSize.Value;
setInitialSize = userPreferredSize.Width == -1 && preferredClientSize.Width == -1;
setInitialSize |= userPreferredSize.Height == -1 && preferredClientSize.Height == -1;
}
else
{
setInitialSize = userPreferredSize.Width == -1 || userPreferredSize.Height == -1;
}

var ret = AutoSize || setInitialSize;

if (Widget.Loaded)
{
PerformAutoSize();
}
return ret;
}

private void PerformAutoSize()
{
if (AutoSize || !setInitialSize)
if (AutoSize || setInitialSize)
{
setInitialSize = true;
setInitialSize = false;
var availableSize = SizeF.PositiveInfinity;
var borderSize = GetBorderSize();
if (UserPreferredSize.Width != -1)
Expand Down Expand Up @@ -855,21 +879,24 @@ public override Size ClientSize
get { return Control.ContentView.Frame.Size.ToEtoSize(); }
set
{
var oldFrame = Control.Frame;
var oldSize = Control.ContentView.Frame;
Control.SetFrameOrigin(new CGPoint(oldFrame.X, (nfloat)Math.Max(0, oldFrame.Y - (value.Height - oldSize.Height))));
Control.SetContentSize(value.ToNS());
if (!Widget.Loaded)
if (value.Height != -1)
{
PreferredClientSize = value;
if (value.Width != -1 && value.Height != -1)
UserPreferredSize = new Size(-1, -1);
else if (value.Width != -1)
UserPreferredSize = new Size(-1, UserPreferredSize.Height);
else if (value.Height != -1)
UserPreferredSize = new Size(UserPreferredSize.Width, -1);
var oldFrame = Control.Frame;
var oldSize = Control.ContentView.Frame;
Control.SetFrameOrigin(new CGPoint(oldFrame.X, (nfloat)Math.Max(0, oldFrame.Y - (value.Height - oldSize.Height))));
}

PreferredClientSize = value;
if (value.Width != -1 && value.Height != -1)
UserPreferredSize = new Size(-1, -1);
else if (value.Width != -1)
UserPreferredSize = new Size(-1, UserPreferredSize.Height);
else if (value.Height != -1)
UserPreferredSize = new Size(UserPreferredSize.Width, -1);
if (!SetAutoSize())
{
Control.SetContentSize(value.ToNS());
}
SetAutoSize();
}
}

Expand Down Expand Up @@ -1031,7 +1058,7 @@ public override void OnLoadComplete(EventArgs e)
initialState = null;
Callback.OnSizeChanged(Widget, EventArgs.Empty);
}
else if (setInitialSize)
else if (!setInitialSize)
Callback.OnSizeChanged(Widget, EventArgs.Empty);
}

Expand Down Expand Up @@ -1062,11 +1089,11 @@ void SetContentSize(CGSize contentSize)
var diffy = clientSize.Height - (int)contentSize.Height;
var diffx = clientSize.Width - (int)contentSize.Width;
var frame = Control.Frame;
if (diffx != 0 || !setInitialSize)
if (diffx != 0 || setInitialSize)
{
frame.Width -= diffx;
}
if (diffy != 0 || !setInitialSize)
if (diffy != 0 || setInitialSize)
{
frame.Y += diffy;
frame.Height -= diffy;
Expand All @@ -1079,12 +1106,20 @@ void SetContentSize(CGSize contentSize)

#endregion

int DisableAutoSize
{
get => Widget.Properties.Get<int>(MacWindow.DisableAutoSize_Key);
set => Widget.Properties.Set(MacWindow.DisableAutoSize_Key, value);
}

public override void InvalidateMeasure()
{
base.InvalidateMeasure();
if (Widget.Loaded && AutoSize && !Widget.IsSuspended)
if (Widget.Loaded && AutoSize && !Widget.IsSuspended && DisableAutoSize == 0)
{
SetContentSize(GetPreferredSize(SizeF.PositiveInfinity).ToNS());
DisableAutoSize++; // prevent recursion
PerformAutoSize();
DisableAutoSize--;
}
}

Expand Down

0 comments on commit 064e8e9

Please sign in to comment.