Skip to content

Commit

Permalink
Mac: Allow interaction with FloatingForm when it has WindowStyle.None…
Browse files Browse the repository at this point in the history
… or Default.
  • Loading branch information
cwensley committed Jun 3, 2022
1 parent 83dd7c3 commit f61fe46
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 78 deletions.
115 changes: 110 additions & 5 deletions src/Eto.Mac/Forms/FloatingFormHandler.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using Eto.Forms;

namespace Eto.Mac.Forms
Expand Down Expand Up @@ -26,25 +27,129 @@ protected override void Initialize()
ShowInTaskbar = false;
}


static readonly object LastOwner_Key = new object();

protected override NSWindowLevel TopmostWindowLevel => NSWindowLevel.Floating;

public override void SetOwner(Window owner)
{
base.SetOwner(owner);

// When this is true, the NSPanel would hide the panel and owner if they aren't key.
// So, only hide on deactivate if it is an ownerless form.
Control.HidesOnDeactivate = owner == null;

SetLevelAdjustment();
}

void SetLevelAdjustment()
{
// only need to adjust level when window style is not utility and we actually want it to be topmost (default for FloatingForm).
var wantsTopmost = Widget.Properties.Get<bool>(Topmost_Key, true);
var owner = Widget.Owner;
var needsLevelAdjust = wantsTopmost && WindowStyle != WindowStyle.Utility && owner != null;

var lastOwner = Widget.Properties.Get<Window>(LastOwner_Key);

if (!needsLevelAdjust)
{
if (lastOwner != null)
{
// no longer need window level adjustments, unregister
lastOwner.GotFocus -= Owner_GotFocus;
lastOwner.LostFocus -= Owner_LostFocus;
Widget.Closed -= Widget_Closed;
Widget.Properties.Set<Window>(LastOwner_Key, null);
}
if (wantsTopmost)
{
SetAsTopmost();
}
return;
}

if (!ReferenceEquals(lastOwner, owner))
{
Widget.Properties.Set(LastOwner_Key, owner);
if (lastOwner != null)
{
lastOwner.GotFocus -= Owner_GotFocus;
lastOwner.LostFocus -= Owner_LostFocus;
Widget.Closed -= Widget_Closed;
}
if (owner != null)
{
owner.GotFocus += Owner_GotFocus;
owner.LostFocus += Owner_LostFocus;
Widget.Closed += Widget_Closed;
}
}

if (lastOwner == null || lastOwner.HasFocus)
SetAsTopmost();
}

private void Widget_Closed(object sender, EventArgs e)
{
var lastOwner = Widget.Properties.Get<Window>(LastOwner_Key);
if (lastOwner != null)
{
// when closed we need to disconnect from owner to prevent leaks
lastOwner.GotFocus -= Owner_GotFocus;
lastOwner.LostFocus -= Owner_LostFocus;
}
}

static readonly object Topmost_Key = new object();

public override bool Topmost
{
get => base.Topmost;
set
{
base.Topmost = value;
// need to remember the preferred state as it can be changed on us when setting the owner
Widget.Properties.Set(Topmost_Key, value, true);
SetLevelAdjustment();
}
}

public override WindowStyle WindowStyle
{
get => base.WindowStyle;
set
{
base.WindowStyle = value;
SetLevelAdjustment();
}
}

private void Owner_GotFocus(object sender, EventArgs e) => SetAsTopmost();

void SetAsTopmost()
{
Control.Level = TopmostWindowLevel;
Control.HidesOnDeactivate = true;
}

private void Owner_LostFocus(object sender, EventArgs e)
{
Control.Level = NSWindowLevel.Normal;
if (Control.IsVisible)
Control.OrderFront(Control);
}

protected override NSPanel CreateControl()
{
var panel = new EtoPanel(new CGRect(0, 0, 200, 200),
NSWindowStyle.Resizable | NSWindowStyle.Closable | NSWindowStyle.Titled,
var panel = new EtoPanel(new CGRect(0, 0, 200, 200),
NSWindowStyle.Resizable | NSWindowStyle.Closable | NSWindowStyle.Titled,
NSBackingStore.Buffered, false);

panel.CanFocus = true;

panel.FloatingPanel = true;
panel.BecomesKeyOnlyIfNeeded = true;

return panel;
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/Eto.Mac/Forms/MacWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ public bool ShowInTaskbar

protected virtual NSWindowLevel TopmostWindowLevel => NSWindowLevel.PopUpMenu;

public bool Topmost
public virtual bool Topmost
{
get => Control.Level >= NSWindowLevel.Floating;
set
Expand Down Expand Up @@ -678,7 +678,7 @@ protected bool SetAutoSize()
}

var ret = AutoSize || setInitialSize;

if (Widget.Loaded)
{
PerformAutoSize();
Expand Down Expand Up @@ -1122,7 +1122,7 @@ public Screen Screen
}
}

public WindowStyle WindowStyle
public virtual WindowStyle WindowStyle
{
get { return Control.StyleMask.ToEtoWindowStyle(); }
set
Expand Down
18 changes: 17 additions & 1 deletion src/Eto.Mac/Forms/NativeFormHandler.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using Eto.Drawing;
using Eto.Forms;

namespace Eto.Mac.Forms
{
Expand All @@ -16,7 +17,22 @@ public NativeFormHandler(NSWindowController windowController)

public override void AttachEvent(string id)
{
// can't attach any events, this is a native window!
// native window, so attach notifications instead of using the delegate so we don't clobber existing functionality
switch (id)
{
case Window.ClosedEvent:
NSNotificationCenter.DefaultCenter.AddObserver(NSWindow.WillCloseNotification, n => Callback.OnClosed(Widget, EventArgs.Empty));
break;
case Window.SizeChangedEvent:
NSNotificationCenter.DefaultCenter.AddObserver(NSWindow.DidResizeNotification, n => Callback.OnSizeChanged(Widget, EventArgs.Empty));
break;
case Window.GotFocusEvent:
NSNotificationCenter.DefaultCenter.AddObserver(NSWindow.DidBecomeKeyNotification, n => Callback.OnGotFocus(Widget, EventArgs.Empty));
break;
case Window.LostFocusEvent:
NSNotificationCenter.DefaultCenter.AddObserver(NSWindow.DidResignKeyNotification, n => Callback.OnGotFocus(Widget, EventArgs.Empty));
break;
}
return;
}

Expand Down
1 change: 1 addition & 0 deletions src/Eto.Wpf/WpfConversions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ public static WindowStyle ToEto(this sw.WindowStyle style)
case sw.WindowStyle.None:
return WindowStyle.None;
case sw.WindowStyle.ThreeDBorderWindow:
case sw.WindowStyle.SingleBorderWindow:
return WindowStyle.Default;
case sw.WindowStyle.ToolWindow:
return WindowStyle.Utility;
Expand Down
Loading

0 comments on commit f61fe46

Please sign in to comment.