mirror of
https://github.com/Stone-Red-Code/DesktopMagic.git
synced 2026-11-02 07:08:31 +01:00
Fix plugin windows not clamping to the selected monitor bounds
This commit is contained in:
@@ -122,34 +122,49 @@ public static class ScreenUtilities
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps an absolute WPF position (DIPs) so that the window (of the given size)
|
||||
/// stays within the screen bounds. This prevents widgets from being moved to another screen.
|
||||
/// Window hook that keeps a window inside the given screen bounds. <see cref="Window.LocationChanged"/>
|
||||
/// fires only after a move has already happened, and the system move loop overrides any correction
|
||||
/// made there on the next mouse move, so the proposed position is adjusted in WM_WINDOWPOSCHANGING
|
||||
/// instead, which every move and resize goes through. The position and the bounds are both in this
|
||||
/// process' screen coordinates, so no DIP conversion is needed.
|
||||
/// </summary>
|
||||
public static Point ClampToScreenBounds(Point topLeft, Size size, System.Drawing.Rectangle bounds)
|
||||
public static IntPtr ClampToScreenHook(IntPtr hwnd, int msg, IntPtr lParam, System.Drawing.Rectangle bounds)
|
||||
{
|
||||
Rect dips = GetScreenDips(bounds);
|
||||
double x = topLeft.X;
|
||||
double y = topLeft.Y;
|
||||
|
||||
if (size.Width <= dips.Width)
|
||||
if (msg != NativeMethods.WM_WINDOWPOSCHANGING || bounds.Width == 0 || bounds.Height == 0)
|
||||
{
|
||||
x = Math.Clamp(x, dips.Left, dips.Right - size.Width);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = dips.Left;
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (size.Height <= dips.Height)
|
||||
NativeMethods.WINDOWPOS pos = Marshal.PtrToStructure<NativeMethods.WINDOWPOS>(lParam);
|
||||
if ((pos.flags & NativeMethods.SWP_NOMOVE) != 0)
|
||||
{
|
||||
y = Math.Clamp(y, dips.Top, dips.Bottom - size.Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
y = dips.Top;
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
return new Point(x, y);
|
||||
int width = pos.cx;
|
||||
int height = pos.cy;
|
||||
if ((pos.flags & NativeMethods.SWP_NOSIZE) != 0)
|
||||
{
|
||||
if (!W32.GetWindowRect(hwnd, out W32.RECT current))
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
width = current.Width;
|
||||
height = current.Height;
|
||||
}
|
||||
|
||||
int x = width <= bounds.Width ? Math.Clamp(pos.x, bounds.Left, bounds.Right - width) : bounds.Left;
|
||||
int y = height <= bounds.Height ? Math.Clamp(pos.y, bounds.Top, bounds.Bottom - height) : bounds.Top;
|
||||
|
||||
if (x != pos.x || y != pos.y)
|
||||
{
|
||||
pos.x = x;
|
||||
pos.y = y;
|
||||
Marshal.StructureToPtr(pos, lParam, false);
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -421,6 +421,9 @@ public partial class PluginWindow : Window, IPluginWindow
|
||||
WindowInteropHelper helper = new(this);
|
||||
_ = WindowPos.SetWindowLong(helper.Handle, WindowPos.GWL_EXSTYLE,
|
||||
WindowPos.GetWindowLong(helper.Handle, WindowPos.GWL_EXSTYLE) | WindowPos.WS_EX_NOACTIVATE);
|
||||
|
||||
HwndSource.FromHwnd(helper.Handle)?.AddHook((IntPtr hwnd, int msg, IntPtr _, IntPtr lParam, ref bool _) =>
|
||||
ScreenUtilities.ClampToScreenHook(hwnd, msg, lParam, screenBounds));
|
||||
}
|
||||
|
||||
private void UpdateImageFromBitmap(Bitmap bitmap, BitmapScalingMode scalingMode)
|
||||
@@ -1394,17 +1397,6 @@ public partial class PluginWindow : Window, IPluginWindow
|
||||
return;
|
||||
}
|
||||
|
||||
System.Windows.Point topLeft = new(Left, Top);
|
||||
System.Windows.Point clamped = ScreenUtilities.ClampToScreenBounds(topLeft, new System.Windows.Size(ActualWidth, ActualHeight), screenBounds);
|
||||
|
||||
if (clamped != topLeft)
|
||||
{
|
||||
isUpdatingPosition = true;
|
||||
Left = clamped.X;
|
||||
Top = clamped.Y;
|
||||
isUpdatingPosition = false;
|
||||
}
|
||||
|
||||
settings.Position = ScreenUtilities.PositionToPercent(new System.Windows.Point(Left, Top), screenBounds);
|
||||
RefreshWindowPixelSize();
|
||||
}
|
||||
|
||||
@@ -218,6 +218,9 @@ public partial class WebPluginWindow : Window, IPluginWindow
|
||||
WindowInteropHelper helper = new(this);
|
||||
_ = WindowPos.SetWindowLong(helper.Handle, WindowPos.GWL_EXSTYLE,
|
||||
WindowPos.GetWindowLong(helper.Handle, WindowPos.GWL_EXSTYLE) | WindowPos.WS_EX_NOACTIVATE);
|
||||
|
||||
HwndSource.FromHwnd(helper.Handle)?.AddHook((IntPtr hwnd, int msg, IntPtr _, IntPtr lParam, ref bool _) =>
|
||||
ScreenUtilities.ClampToScreenHook(hwnd, msg, lParam, screenBounds));
|
||||
}
|
||||
|
||||
private async void Window_ContentRendered(object? sender, EventArgs e)
|
||||
@@ -436,17 +439,6 @@ public partial class WebPluginWindow : Window, IPluginWindow
|
||||
return;
|
||||
}
|
||||
|
||||
Point topLeft = new(Left, Top);
|
||||
Point clamped = ScreenUtilities.ClampToScreenBounds(topLeft, new Size(ActualWidth, ActualHeight), screenBounds);
|
||||
|
||||
if (clamped != topLeft)
|
||||
{
|
||||
isUpdatingPosition = true;
|
||||
Left = clamped.X;
|
||||
Top = clamped.Y;
|
||||
isUpdatingPosition = false;
|
||||
}
|
||||
|
||||
settings.Position = ScreenUtilities.PositionToPercent(new Point(Left, Top), screenBounds);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user