Skip to content

Commit

Permalink
Merge pull request #2646 from cwensley/curtis/window-focus-and-bringt…
Browse files Browse the repository at this point in the history
…ofront

Make Window.Focus() and BringToFront() consistent across platforms
  • Loading branch information
cwensley committed Apr 24, 2024
2 parents 4721256 + c312ea1 commit 8819ec1
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 112 deletions.
14 changes: 4 additions & 10 deletions src/Eto.Gtk/Forms/GtkWindow.cs
Expand Up @@ -781,17 +781,11 @@ public Screen Screen
}
}

public void BringToFront()
{
Control.Present();
}
protected override void GrabFocus() => Control.Present();

public void SendToBack()
{
var gdkWindow = Control.GetWindow();
if (gdkWindow != null)
gdkWindow.Lower();
}
public void BringToFront() => Control.GetWindow()?.Raise();

public void SendToBack() => Control.GetWindow()?.Lower();

public virtual void SetOwner(Window owner)
{
Expand Down
10 changes: 3 additions & 7 deletions src/Eto.Mac/Forms/MacWindow.cs
Expand Up @@ -342,7 +342,7 @@ static void HandleGotFocus(object sender, EventArgs e)
if (handler == null)
return;
handler.Callback.OnGotFocus(handler.Widget, EventArgs.Empty);
if (GetHandler(handler.Control.FirstResponder) is IMacViewHandler ctlHandler)
if (GetHandler(handler.Control.FirstResponder) is IMacViewHandler ctlHandler && ctlHandler != handler)
{
ctlHandler.Callback.OnGotFocus(ctlHandler.Widget, EventArgs.Empty);
}
Expand All @@ -354,7 +354,7 @@ static void HandleLostFocus(object sender, EventArgs e)
if (handler == null)
return;

if (GetHandler(handler.Control.FirstResponder) is IMacViewHandler ctlHandler)
if (GetHandler(handler.Control.FirstResponder) is IMacViewHandler ctlHandler && ctlHandler != handler)
{
ctlHandler.Callback.OnLostFocus(ctlHandler.Widget, EventArgs.Empty);
}
Expand Down Expand Up @@ -905,10 +905,7 @@ public Icon Icon
}
}

public override void Focus()
{
Control.BecomeFirstResponder();
}
public override void Focus() => Control.MakeKeyAndOrderFront(Control);

public string Id { get; set; }

Expand Down Expand Up @@ -1243,7 +1240,6 @@ public virtual WindowStyle WindowStyle
public void BringToFront()
{
Control.OrderFront(Control);
Control.MakeKeyWindow();
}

public void SendToBack()
Expand Down
8 changes: 8 additions & 0 deletions src/Eto.WinForms/Forms/FormHandler.cs
Expand Up @@ -177,6 +177,14 @@ public bool CanFocus
}
}

public override void Focus()
{
if (!CanFocus)
BringToFront();
else
base.Focus();
}

EtoForm EtoFormControl => Control as EtoForm;
}
}
6 changes: 4 additions & 2 deletions src/Eto.WinForms/Forms/WindowHandler.cs
Expand Up @@ -549,8 +549,10 @@ public virtual void BringToFront()
{
if (Control.WindowState == swf.FormWindowState.Minimized)
Control.WindowState = swf.FormWindowState.Normal;
Control.BringToFront();
Control.Activate();

var hWnd = NativeHandle;
if (hWnd != IntPtr.Zero)
Win32.SetWindowPos(hWnd, Win32.HWND_TOP, 0, 0, 0, 0, Win32.SWP.NOSIZE | Win32.SWP.NOMOVE | Win32.SWP.NOACTIVATE);
}

public void SendToBack() => Control.SendToBack();
Expand Down
2 changes: 1 addition & 1 deletion src/Eto.WinForms/Forms/WindowsControl.cs
Expand Up @@ -693,7 +693,7 @@ public virtual void ResumeLayout()
Control.ResumeLayout();
}

public void Focus()
public virtual void Focus()
{
if (Widget.Loaded && Control.IsHandleCreated)
Control.Focus();
Expand Down
10 changes: 10 additions & 0 deletions src/Eto.Wpf/Forms/FormHandler.cs
Expand Up @@ -71,5 +71,15 @@ public bool CanFocus
SetStyle(Win32.WS.CHILD, !value);
}
}

public override void Focus()
{
if (!Control.Focusable)
BringToFront();
else
base.Focus();
}


}
}
11 changes: 3 additions & 8 deletions src/Eto.Wpf/Forms/WpfWindow.cs
Expand Up @@ -972,14 +972,9 @@ public void BringToFront()
if (Control.WindowState == sw.WindowState.Minimized)
Control.WindowState = sw.WindowState.Normal;

if (!Control.Focusable)
{
var hWnd = NativeHandle;
if (hWnd != IntPtr.Zero)
Win32.SetWindowPos(hWnd, Win32.HWND_TOP, 0, 0, 0, 0, Win32.SWP.NOSIZE | Win32.SWP.NOMOVE);
}
else
Control.Activate();
var hWnd = NativeHandle;
if (hWnd != IntPtr.Zero)
Win32.SetWindowPos(hWnd, Win32.HWND_TOP, 0, 0, 0, 0, Win32.SWP.NOSIZE | Win32.SWP.NOMOVE | Win32.SWP.NOACTIVATE);
}

public void SendToBack()
Expand Down
76 changes: 22 additions & 54 deletions src/Eto/Forms/Controls/Control.cs
Expand Up @@ -866,7 +866,7 @@ internal virtual void InternalEnsureLayout()
/// or it can be captured explicitly via <see cref="CaptureMouse"/>.
/// </remarks>
public bool IsMouseCaptured => Handler.IsMouseCaptured;

/// <summary>
/// Captures all mouse events to this control.
/// </summary>
Expand All @@ -877,7 +877,7 @@ internal virtual void InternalEnsureLayout()
/// </remarks>
/// <returns><c>true</c> if the mouse was captured, false otherwise.</returns>
public bool CaptureMouse() => Handler.CaptureMouse();

/// <summary>
/// Releases the mouse capture after a call to <see cref="CaptureMouse"/>.
/// </summary>
Expand Down Expand Up @@ -998,10 +998,7 @@ public new Container FindParent(Type type, string id = null)
/// </summary>
/// <returns>The parent if found, or null if not found.</returns>
/// <param name="id">Identifier of the parent control to find.</param>
public new Container FindParent(string id)
{
return FindParent(null, id);
}
public new Container FindParent(string id) => FindParent(null, id);

/// <summary>
/// Detaches the control by removing it from its parent
Expand Down Expand Up @@ -1041,7 +1038,7 @@ public void AttachNative()
{
if (VisualParent != null)
throw new InvalidOperationException("You can only attach a parentless control");

if (IsAttached)
return;

Expand Down Expand Up @@ -1128,18 +1125,13 @@ public Color BackgroundColor
/// Gets a value indicating whether this instance has the keyboard input focus.
/// </summary>
/// <value><c>true</c> if this instance has focus; otherwise, <c>false</c>.</value>
public virtual bool HasFocus
{
get { return Handler.HasFocus; }
}
public virtual bool HasFocus => Handler.HasFocus;

/// <summary>
/// Attempts to set the keyboard input focus to this control, or the first child that accepts focus
/// Attempts to set the keyboard input focus to this control, or the first child that accepts focus.
/// For Windows, this will bring it to front and activate it.
/// </summary>
public virtual void Focus()
{
Handler.Focus();
}
public virtual void Focus() => Handler.Focus();


static readonly object SuspendCount_Key = new object();
Expand All @@ -1156,7 +1148,7 @@ int SuspendCount
/// <seealso cref="SuspendLayout"/>
/// <seealso cref="ResumeLayout"/>
/// <value><c>true</c> if this instance is suspended; otherwise, <c>false</c>.</value>
public bool IsSuspended { get { return SuspendCount > 0; } }
public bool IsSuspended => SuspendCount > 0;

/// <summary>
/// Suspends the layout of child controls
Expand Down Expand Up @@ -1218,10 +1210,7 @@ public Window ParentWindow
/// </remarks>
/// <value>The supported platform commands.</value>
/// <seealso cref="MapPlatformCommand"/>
public IEnumerable<string> SupportedPlatformCommands
{
get { return Handler.SupportedPlatformCommands; }
}
public IEnumerable<string> SupportedPlatformCommands => Handler.SupportedPlatformCommands;

/// <summary>
/// Specifies a command to execute for a platform-specific command
Expand All @@ -1248,59 +1237,41 @@ public IEnumerable<string> SupportedPlatformCommands
/// <param name="systemCommand">System command</param>
/// <param name="command">Command to execute, or null to restore to the default behavior</param>
/// <seealso cref="SupportedPlatformCommands"/>
public void MapPlatformCommand(string systemCommand, Command command)
{
Handler.MapPlatformCommand(systemCommand, command);
}
public void MapPlatformCommand(string systemCommand, Command command) => Handler.MapPlatformCommand(systemCommand, command);

/// <summary>
/// Converts a point from screen space to control space.
/// </summary>
/// <returns>The point in control space</returns>
/// <param name="point">Point in screen space</param>
public PointF PointFromScreen(PointF point)
{
return Handler.PointFromScreen(point);
}
public PointF PointFromScreen(PointF point) => Handler.PointFromScreen(point);

/// <summary>
/// Converts a point from control space to screen space
/// </summary>
/// <returns>The point in screen space</returns>
/// <param name="point">Point in control space</param>
public PointF PointToScreen(PointF point)
{
return Handler.PointToScreen(point);
}
public PointF PointToScreen(PointF point) => Handler.PointToScreen(point);

/// <summary>
/// Converts a rectangle from screen space to control space.
/// </summary>
/// <returns>The rectangle in control space</returns>
/// <param name="rect">Rectangle in screen space</param>
public RectangleF RectangleToScreen(RectangleF rect)
{
return new RectangleF(PointToScreen(rect.Location), PointToScreen(rect.EndLocation));
}
public RectangleF RectangleToScreen(RectangleF rect) => new RectangleF(PointToScreen(rect.Location), PointToScreen(rect.EndLocation));

/// <summary>
/// Converts a rectangle from control space to screen space
/// </summary>
/// <returns>The rectangle in screen space</returns>
/// <param name="rect">Rectangle in control space</param>
public RectangleF RectangleFromScreen(RectangleF rect)
{
return new RectangleF(PointFromScreen(rect.Location), PointFromScreen(rect.EndLocation));
}
public RectangleF RectangleFromScreen(RectangleF rect) => new RectangleF(PointFromScreen(rect.Location), PointFromScreen(rect.EndLocation));

/// <summary>
/// Gets the bounding rectangle of this control relative to its container
/// </summary>
/// <value>The bounding rectangle of the control</value>
public Rectangle Bounds
{
get { return new Rectangle(Location, Size); }
}
public Rectangle Bounds => new Rectangle(Location, Size);

/// <summary>
/// Gets the location of the control as positioned by the container
Expand All @@ -1310,10 +1281,7 @@ public Rectangle Bounds
/// This can be used to determine where the control is for overlaying floating windows, menus, etc.
/// </remarks>
/// <value>The current location of the control</value>
public Point Location
{
get { return Handler.Location; }
}
public Point Location => Handler.Location;

/// <summary>
/// Gets or sets the type of cursor to use when the mouse is hovering over the control
Expand Down Expand Up @@ -1435,7 +1403,7 @@ protected override void OnStyleChanged(EventArgs e)
/// <param name="widget">Widget to style.</param>
/// <param name="style">Style of the widget to apply.</param>
protected virtual void ApplyStyles(object widget, string style) => Parent?.ApplyStyles(widget, Style);

/// <summary>
/// Shows a print dialog to print the specified control
/// </summary>
Expand All @@ -1447,7 +1415,7 @@ public void Print()
dlg.ShowDialog(this, doc);
}
}


/// <summary>
/// Handles the disposal of this control
Expand Down Expand Up @@ -2039,7 +2007,7 @@ public new interface IHandler : Widget.IHandler
/// <param name="availableSize">The available size to determine the preferred size</param>
/// <returns>The preferred size this control would like to be, which can be larger than the specified <paramref name="availableSize" />.</returns>
SizeF GetPreferredSize(SizeF availableSize);

/// <summary>
/// Updates the layout of this control if necessary.
/// </summary>
Expand All @@ -2050,7 +2018,7 @@ public new interface IHandler : Widget.IHandler
/// This is useful when you need to know the dimensions of the control immediately.
/// </remarks>
void UpdateLayout();

/// <summary>
/// Gets a value indicating this control currently has mouse capture
/// </summary>
Expand All @@ -2070,7 +2038,7 @@ public new interface IHandler : Widget.IHandler
/// </remarks>
/// <returns><c>true</c> if the mouse was captured, false otherwise.</returns>
bool CaptureMouse();

/// <summary>
/// Releases the mouse capture after a call to <see cref="CaptureMouse"/>.
/// </summary>
Expand Down
14 changes: 4 additions & 10 deletions src/Eto/Forms/Window.cs
Expand Up @@ -533,20 +533,14 @@ public WindowStyle WindowStyle
}

/// <summary>
/// Brings the window in front of all other windows in the z-order.
/// Brings the window in front of all other windows in the z-order. This should not activate/focus the window.
/// </summary>
public void BringToFront()
{
Handler.BringToFront();
}
public void BringToFront() => Handler.BringToFront();

/// <summary>
/// Sends the window behind all other windows in the z-order.
/// Sends the window behind all other windows in the z-order, and will remain active if it has focus.
/// </summary>
public void SendToBack()
{
Handler.SendToBack();
}
public void SendToBack() => Handler.SendToBack();

/// <summary>
/// Raises the <see cref="BindableWidget.DataContextChanged"/> event
Expand Down

0 comments on commit 8819ec1

Please sign in to comment.