diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index bfd7e4b87..d7b29aa46 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -195,6 +195,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings public double WindowLeft { get; set; } public double WindowTop { get; set; } + public double CustomWindowLeft { get; set; } = 0; + public double CustomWindowTop { get; set; } = 0; public int MaxResultsToShow { get; set; } = 5; public int ActivateTimes { get; set; } @@ -227,7 +229,9 @@ namespace Flow.Launcher.Infrastructure.UserSettings } public bool LeaveCmdOpen { get; set; } public bool HideWhenDeactivated { get; set; } = true; - public SearchWindowPositions SearchWindowPosition { get; set; } = SearchWindowPositions.MouseScreenCenter; + + public SearchWindowScreens SearchWindowScreen { get; set; } = SearchWindowScreens.RememberLastLaunchLocation; + public SearchWindowAligns SearchWindowAlign { get; set; } = SearchWindowAligns.Center; public bool IgnoreHotkeysOnFullscreen { get; set; } public HttpProxy Proxy { get; set; } = new HttpProxy(); @@ -253,12 +257,19 @@ namespace Flow.Launcher.Infrastructure.UserSettings Light, Dark } - public enum SearchWindowPositions + public enum SearchWindowScreens { RememberLastLaunchLocation, - MouseScreenCenter, - MouseScreenCenterTop, - MouseScreenLeftTop, - MouseScreenRightTop + MouseScreen, + PrimaryScreen, + SecondaryScreen, + CustomPosition + } + public enum SearchWindowAligns + { + Center, + CenterTop, + LeftTop, + RightTop } } diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 9e86d9305..a39adac54 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -38,11 +38,15 @@ Hide Flow Launcher when focus is lost Do not show new version notifications Search Window Position - Remember Last Position - Mouse Focused Screen - Center - Mouse Focused Screen - Center Top - Mouse Focused Screen - Left Top - Mouse Focused Screen - Right Top + Remember Last Position + Mouse Focused Monitor + Primary Monitor + Secondary Monitor + Custom Position + Center + Center Top + Left Top + Right Top Language Last Query Style Show/Hide previous results when Flow Launcher is reactivated. diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 550648b24..a465345be 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -24,6 +24,7 @@ using System.Windows.Threading; using System.Windows.Data; using ModernWpf.Controls; using Key = System.Windows.Input.Key; +using System.Threading; namespace Flow.Launcher { @@ -201,29 +202,39 @@ namespace Flow.Launcher private void InitializePosition() { - switch (_settings.SearchWindowPosition) + if (_settings.SearchWindowScreen == SearchWindowScreens.RememberLastLaunchLocation) { - case SearchWindowPositions.RememberLastLaunchLocation: - Top = _settings.WindowTop; - Left = _settings.WindowLeft; - break; - case SearchWindowPositions.MouseScreenCenter: - Left = HorizonCenter(); - Top = VerticalCenter(); - break; - case SearchWindowPositions.MouseScreenCenterTop: - Left = HorizonCenter(); - Top = 10; - break; - case SearchWindowPositions.MouseScreenLeftTop: - Left = 10; - Top = 10; - break; - case SearchWindowPositions.MouseScreenRightTop: - Left = HorizonRight(); - Top = 10; - break; + Top = _settings.WindowTop; + Left = _settings.WindowLeft; } + else if (_settings.SearchWindowScreen == SearchWindowScreens.CustomPosition) + { + Top = _settings.CustomWindowTop; + Left = _settings.CustomWindowLeft; + } + else + { + switch (_settings.SearchWindowAlign) + { + case SearchWindowAligns.Center: + Left = HorizonCenter(); + Top = VerticalCenter(); + break; + case SearchWindowAligns.CenterTop: + Left = HorizonCenter(); + Top = 10; + break; + case SearchWindowAligns.LeftTop: + Left = HorizonLeft(); + Top = 10; + break; + case SearchWindowAligns.RightTop: + Left = HorizonRight(); + Top = 10; + break; + } + } + } private void UpdateNotifyIconText() @@ -503,7 +514,7 @@ namespace Flow.Launcher { if (_animating) return; - if (_settings.SearchWindowPosition == SearchWindowPositions.RememberLastLaunchLocation) + if (_settings.SearchWindowScreen == SearchWindowScreens.RememberLastLaunchLocation) { _settings.WindowLeft = Left; _settings.WindowTop = Top; @@ -523,9 +534,32 @@ namespace Flow.Launcher } } + public Screen SelectedScreen() + { + if (_settings.SearchWindowScreen == SearchWindowScreens.MouseScreen) + { + var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); + return screen; + } + else if (_settings.SearchWindowScreen == SearchWindowScreens.PrimaryScreen) + { + var screen = Screen.PrimaryScreen; + return screen; + } + else if (_settings.SearchWindowScreen == SearchWindowScreens.SecondaryScreen) + { + var screen = Screen.AllScreens[1]; + return screen; + } + else + { + var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); + return screen; + } + } public double HorizonCenter() { - var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); + var screen = SelectedScreen(); var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0); var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0); var left = (dip2.X - ActualWidth) / 2 + dip1.X; @@ -534,7 +568,7 @@ namespace Flow.Launcher public double VerticalCenter() { - var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); + var screen = SelectedScreen(); var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y); var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Height); var top = (dip2.Y - QueryTextBox.ActualHeight) / 4 + dip1.Y; @@ -543,10 +577,19 @@ namespace Flow.Launcher public double HorizonRight() { - var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); + var screen = SelectedScreen(); var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0); var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0); - var left = (dip2.X - ActualWidth) - 10; + var left = (dip1.X + dip2.X - ActualWidth) - 10; + return left; + } + + public double HorizonLeft() + { + var screen = SelectedScreen(); + var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0); + var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0); + var left = dip1.X + 10; return left; } diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 07f23ff6a..4a16e9610 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -698,17 +698,70 @@ - + + + + + + + + + + + + + + + + diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index 37587ce59..7e3060384 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -22,6 +22,7 @@ using Flow.Launcher.Plugin.SharedModels; using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.Input; using System.Globalization; +using static Flow.Launcher.ViewModel.SettingWindowViewModel; namespace Flow.Launcher.ViewModel { @@ -463,23 +464,50 @@ namespace Flow.Launcher.ViewModel } } - public class SearchWindowPosition + public class SearchWindowScreen { public string Display { get; set; } - public SearchWindowPositions Value { get; set; } + public SearchWindowScreens Value { get; set; } } - public List SearchWindowPositions + public List SearchWindowScreens { get { - List modes = new List(); - var enums = (SearchWindowPositions[])Enum.GetValues(typeof(SearchWindowPositions)); + List modes = new List(); + var enums = (SearchWindowScreens[])Enum.GetValues(typeof(SearchWindowScreens)); foreach (var e in enums) { - var key = $"SearchWindowPosition{e}"; + var key = $"SearchWindowScreen{e}"; var display = _translater.GetTranslation(key); - var m = new SearchWindowPosition + var m = new SearchWindowScreen + { + Display = display, + Value = e, + }; + modes.Add(m); + } + return modes; + } + } + + public class SearchWindowAlign + { + public string Display { get; set; } + public SearchWindowAligns Value { get; set; } + } + + public List SearchWindowAligns + { + get + { + List modes = new List(); + var enums = (SearchWindowAligns[])Enum.GetValues(typeof(SearchWindowAligns)); + foreach (var e in enums) + { + var key = $"SearchWindowAlign{e}"; + var display = _translater.GetTranslation(key); + var m = new SearchWindowAlign { Display = display, Value = e, };