Skip to content

Commit 7023f83

Browse files
authored
Merge pull request #3537 from Flow-Launcher/fix_right_top_position
Fix Vertical Window Positioning with Multiple Monitors
2 parents 86a3b0b + b96a69a commit 7023f83

File tree

3 files changed

+109
-12
lines changed

3 files changed

+109
-12
lines changed

Flow.Launcher.Infrastructure/UserSettings/Settings.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,10 @@ public SearchPrecisionScore QuerySearchPrecision
293293

294294
public double WindowLeft { get; set; }
295295
public double WindowTop { get; set; }
296+
public double PreviousScreenWidth { get; set; }
297+
public double PreviousScreenHeight { get; set; }
298+
public double PreviousDpiX { get; set; }
299+
public double PreviousDpiY { get; set; }
296300

297301
/// <summary>
298302
/// Custom left position on selected monitor

Flow.Launcher/MainWindow.xaml.cs

Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -711,8 +711,26 @@ void InitializePositionInner()
711711
{
712712
if (_settings.SearchWindowScreen == SearchWindowScreens.RememberLastLaunchLocation)
713713
{
714-
Top = _settings.WindowTop;
714+
var previousScreenWidth = _settings.PreviousScreenWidth;
715+
var previousScreenHeight = _settings.PreviousScreenHeight;
716+
GetDpi(out var previousDpiX, out var previousDpiY);
717+
718+
_settings.PreviousScreenWidth = SystemParameters.VirtualScreenWidth;
719+
_settings.PreviousScreenHeight = SystemParameters.VirtualScreenHeight;
720+
GetDpi(out var currentDpiX, out var currentDpiY);
721+
722+
if (previousScreenWidth != 0 && previousScreenHeight != 0 &&
723+
previousDpiX != 0 && previousDpiY != 0 &&
724+
(previousScreenWidth != SystemParameters.VirtualScreenWidth ||
725+
previousScreenHeight != SystemParameters.VirtualScreenHeight ||
726+
previousDpiX != currentDpiX || previousDpiY != currentDpiY))
727+
{
728+
AdjustPositionForResolutionChange();
729+
return;
730+
}
731+
715732
Left = _settings.WindowLeft;
733+
Top = _settings.WindowTop;
716734
}
717735
else
718736
{
@@ -725,27 +743,73 @@ void InitializePositionInner()
725743
break;
726744
case SearchWindowAligns.CenterTop:
727745
Left = HorizonCenter(screen);
728-
Top = 10;
746+
Top = VerticalTop(screen);
729747
break;
730748
case SearchWindowAligns.LeftTop:
731749
Left = HorizonLeft(screen);
732-
Top = 10;
750+
Top = VerticalTop(screen);
733751
break;
734752
case SearchWindowAligns.RightTop:
735753
Left = HorizonRight(screen);
736-
Top = 10;
754+
Top = VerticalTop(screen);
737755
break;
738756
case SearchWindowAligns.Custom:
739-
Left = Win32Helper.TransformPixelsToDIP(this,
740-
screen.WorkingArea.X + _settings.CustomWindowLeft, 0).X;
741-
Top = Win32Helper.TransformPixelsToDIP(this, 0,
742-
screen.WorkingArea.Y + _settings.CustomWindowTop).Y;
757+
var customLeft = Win32Helper.TransformPixelsToDIP(this,
758+
screen.WorkingArea.X + _settings.CustomWindowLeft, 0);
759+
var customTop = Win32Helper.TransformPixelsToDIP(this, 0,
760+
screen.WorkingArea.Y + _settings.CustomWindowTop);
761+
Left = customLeft.X;
762+
Top = customTop.Y;
743763
break;
744764
}
745765
}
746766
}
747767
}
748768

769+
private void AdjustPositionForResolutionChange()
770+
{
771+
var screenWidth = SystemParameters.VirtualScreenWidth;
772+
var screenHeight = SystemParameters.VirtualScreenHeight;
773+
GetDpi(out var currentDpiX, out var currentDpiY);
774+
775+
var previousLeft = _settings.WindowLeft;
776+
var previousTop = _settings.WindowTop;
777+
GetDpi(out var previousDpiX, out var previousDpiY);
778+
779+
var widthRatio = screenWidth / _settings.PreviousScreenWidth;
780+
var heightRatio = screenHeight / _settings.PreviousScreenHeight;
781+
var dpiXRatio = currentDpiX / previousDpiX;
782+
var dpiYRatio = currentDpiY / previousDpiY;
783+
784+
var newLeft = previousLeft * widthRatio * dpiXRatio;
785+
var newTop = previousTop * heightRatio * dpiYRatio;
786+
787+
var screenLeft = SystemParameters.VirtualScreenLeft;
788+
var screenTop = SystemParameters.VirtualScreenTop;
789+
790+
var maxX = screenLeft + screenWidth - ActualWidth;
791+
var maxY = screenTop + screenHeight - ActualHeight;
792+
793+
Left = Math.Max(screenLeft, Math.Min(newLeft, maxX));
794+
Top = Math.Max(screenTop, Math.Min(newTop, maxY));
795+
}
796+
797+
private void GetDpi(out double dpiX, out double dpiY)
798+
{
799+
var source = PresentationSource.FromVisual(this);
800+
if (source != null && source.CompositionTarget != null)
801+
{
802+
var matrix = source.CompositionTarget.TransformToDevice;
803+
dpiX = 96 * matrix.M11;
804+
dpiY = 96 * matrix.M22;
805+
}
806+
else
807+
{
808+
dpiX = 96;
809+
dpiY = 96;
810+
}
811+
}
812+
749813
private Screen SelectedScreen()
750814
{
751815
Screen screen;
@@ -806,6 +870,13 @@ private double HorizonLeft(Screen screen)
806870
return left;
807871
}
808872

873+
public double VerticalTop(Screen screen)
874+
{
875+
var dip1 = Win32Helper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y);
876+
var top = dip1.Y + 10;
877+
return top;
878+
}
879+
809880
#endregion
810881

811882
#region Window Animation

Flow.Launcher/SettingWindow.xaml.cs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,18 +137,40 @@ public void UpdatePositionAndState()
137137

138138
if (previousTop == null || previousLeft == null || !IsPositionValid(previousTop.Value, previousLeft.Value))
139139
{
140-
Top = WindowTop();
141-
Left = WindowLeft();
140+
SetWindowPosition(WindowTop(), WindowLeft());
142141
}
143142
else
144143
{
145-
Top = previousTop.Value;
146-
Left = previousLeft.Value;
144+
var left = _settings.SettingWindowLeft.Value;
145+
var top = _settings.SettingWindowTop.Value;
146+
AdjustWindowPosition(ref top, ref left);
147+
SetWindowPosition(top, left);
147148
}
148149

149150
WindowState = _settings.SettingWindowState;
150151
}
151152

153+
private void SetWindowPosition(double top, double left)
154+
{
155+
// Ensure window does not exceed screen boundaries
156+
top = Math.Max(top, SystemParameters.VirtualScreenTop);
157+
left = Math.Max(left, SystemParameters.VirtualScreenLeft);
158+
top = Math.Min(top, SystemParameters.VirtualScreenHeight - ActualHeight);
159+
left = Math.Min(left, SystemParameters.VirtualScreenWidth - ActualWidth);
160+
161+
Top = top;
162+
Left = left;
163+
}
164+
165+
private void AdjustWindowPosition(ref double top, ref double left)
166+
{
167+
// Adjust window position if it exceeds screen boundaries
168+
top = Math.Max(top, SystemParameters.VirtualScreenTop);
169+
left = Math.Max(left, SystemParameters.VirtualScreenLeft);
170+
top = Math.Min(top, SystemParameters.VirtualScreenHeight - ActualHeight);
171+
left = Math.Min(left, SystemParameters.VirtualScreenWidth - ActualWidth);
172+
}
173+
152174
private static bool IsPositionValid(double top, double left)
153175
{
154176
foreach (var screen in Screen.AllScreens)

0 commit comments

Comments
 (0)