diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 0ad432ffe9..e25f3a342f 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -663,6 +663,7 @@ ERRORTITLE esize estdir etcore +etcoreapp etl etw EUQ diff --git a/src/common/ManagedCommon/StartupPosition.cs b/src/common/ManagedCommon/StartupPosition.cs new file mode 100644 index 0000000000..ae316eee36 --- /dev/null +++ b/src/common/ManagedCommon/StartupPosition.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace ManagedCommon +{ + public enum StartupPosition + { + Cursor, + PrimaryMonitor, + Focus, + } +} diff --git a/src/modules/launcher/PowerLauncher/MainWindow.xaml.cs b/src/modules/launcher/PowerLauncher/MainWindow.xaml.cs index 2345cb2069..98b8a45921 100644 --- a/src/modules/launcher/PowerLauncher/MainWindow.xaml.cs +++ b/src/modules/launcher/PowerLauncher/MainWindow.xaml.cs @@ -207,7 +207,7 @@ namespace PowerLauncher /// X co-ordinate of main window top left corner private double WindowLeft() { - var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); + var screen = GetScreen(); 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; @@ -216,13 +216,30 @@ namespace PowerLauncher private double WindowTop() { - var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); + var screen = GetScreen(); var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y); var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Height); var top = ((dip2.Y - SearchBox.ActualHeight) / 4) + dip1.Y; return top; } + private Screen GetScreen() + { + ManagedCommon.StartupPosition position = _settings.StartupPosition; + switch (position) + { + case ManagedCommon.StartupPosition.PrimaryMonitor: + return Screen.PrimaryScreen; + case ManagedCommon.StartupPosition.Focus: + IntPtr foregroundWindowHandle = NativeMethods.GetForegroundWindow(); + Screen activeScreen = Screen.FromHandle(foregroundWindowHandle); + return activeScreen; + case ManagedCommon.StartupPosition.Cursor: + default: + return Screen.FromPoint(System.Windows.Forms.Cursor.Position); + } + } + private void Launcher_KeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Tab && Keyboard.IsKeyDown(Key.LeftShift)) diff --git a/src/modules/launcher/PowerLauncher/SettingsWatcher.cs b/src/modules/launcher/PowerLauncher/SettingsWatcher.cs index 68641213cc..31bcaaf4d8 100644 --- a/src/modules/launcher/PowerLauncher/SettingsWatcher.cs +++ b/src/modules/launcher/PowerLauncher/SettingsWatcher.cs @@ -126,6 +126,11 @@ namespace PowerLauncher _themeManager.ChangeTheme(_settings.Theme, true); } + if (_settings.StartupPosition != overloadSettings.Properties.Position) + { + _settings.StartupPosition = overloadSettings.Properties.Position; + } + retry = false; } diff --git a/src/modules/launcher/Wox.Infrastructure/UserSettings/PowerToysRunSettings.cs b/src/modules/launcher/Wox.Infrastructure/UserSettings/PowerToysRunSettings.cs index e01121be19..c30f98ff53 100644 --- a/src/modules/launcher/Wox.Infrastructure/UserSettings/PowerToysRunSettings.cs +++ b/src/modules/launcher/Wox.Infrastructure/UserSettings/PowerToysRunSettings.cs @@ -47,6 +47,8 @@ namespace Wox.Infrastructure.UserSettings public Theme Theme { get; set; } = Theme.System; + public StartupPosition StartupPosition { get; set; } = StartupPosition.Cursor; + public string QueryBoxFont { get; set; } = FontFamily.GenericSansSerif.Name; public string QueryBoxFontStyle { get; set; } diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/PowerLauncherProperties.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/PowerLauncherProperties.cs index 6723300b24..d4191871aa 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/PowerLauncherProperties.cs +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/PowerLauncherProperties.cs @@ -45,6 +45,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library [JsonPropertyName("theme")] public Theme Theme { get; set; } + [JsonPropertyName("startupPosition")] + public StartupPosition Position { get; set; } + public PowerLauncherProperties() { OpenPowerLauncher = new HotkeySettings(false, false, true, false, 32); @@ -57,6 +60,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library ClearInputOnLaunch = false; MaximumNumberOfResults = 4; Theme = Theme.System; + Position = StartupPosition.Cursor; } } } diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/PowerLauncherViewModel.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/PowerLauncherViewModel.cs index 668fe902ea..9abe73f2d4 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/PowerLauncherViewModel.cs +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/PowerLauncherViewModel.cs @@ -22,6 +22,10 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels private bool _isLightThemeRadioButtonChecked; private bool _isSystemThemeRadioButtonChecked; + private bool _isCursorPositionRadioButtonChecked; + private bool _isPrimaryMonitorPositionRadioButtonChecked; + private bool _isFocusPositionRadioButtonChecked; + private GeneralSettings GeneralSettingsConfig { get; set; } private readonly ISettingsUtils _settingsUtils; @@ -89,6 +93,19 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels break; } + switch (settings.Properties.Position) + { + case StartupPosition.Cursor: + _isCursorPositionRadioButtonChecked = true; + break; + case StartupPosition.PrimaryMonitor: + _isPrimaryMonitorPositionRadioButtonChecked = true; + break; + case StartupPosition.Focus: + _isFocusPositionRadioButtonChecked = true; + break; + } + foreach (var plugin in Plugins) { plugin.PropertyChanged += OnPluginInfoChange; @@ -243,6 +260,66 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels } } + public bool IsCursorPositionRadioButtonChecked + { + get + { + return _isCursorPositionRadioButtonChecked; + } + + set + { + if (value == true) + { + settings.Properties.Position = StartupPosition.Cursor; + } + + _isCursorPositionRadioButtonChecked = value; + + UpdateSettings(); + } + } + + public bool IsPrimaryMonitorPositionRadioButtonChecked + { + get + { + return _isPrimaryMonitorPositionRadioButtonChecked; + } + + set + { + if (value == true) + { + settings.Properties.Position = StartupPosition.PrimaryMonitor; + } + + _isPrimaryMonitorPositionRadioButtonChecked = value; + + UpdateSettings(); + } + } + + public bool IsFocusPositionRadioButtonChecked + { + get + { + return _isFocusPositionRadioButtonChecked; + } + + set + { + if (value == true) + { + settings.Properties.Position = StartupPosition.Focus; + } + + _isFocusPositionRadioButtonChecked = value; + + UpdateSettings(); + } + } + public HotkeySettings OpenPowerLauncher { get diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw index 10af378234..250ed62400 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw @@ -1151,4 +1151,20 @@ Win + Shift + O to toggle your video PowerToys Settings - \ No newline at end of file + + Position & appearance + + + Show PowerToys Run on + as in Show PowerToys Run on primary monitor + + + Monitor with mouse cursor + + + Monitor with focused window + + + Primary monitor + + diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml index 72a99ee7d2..00fea94b85 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml @@ -148,9 +148,30 @@ IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.EnablePowerLauncher}" /> - + + + + + + + + +