Merge pull request #1978 from onesounds/PrimaryMonitor

This commit is contained in:
DB P 2023-03-20 21:49:01 +09:00 committed by GitHub
commit 109796c748
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 307 additions and 78 deletions

View file

@ -195,6 +195,17 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public double WindowLeft { get; set; }
public double WindowTop { get; set; }
/// <summary>
/// Custom left position on selected monitor
/// </summary>
public double CustomWindowLeft { get; set; } = 0;
/// <summary>
/// Custom top position on selected monitor
/// </summary>
public double CustomWindowTop { get; set; } = 0;
public int MaxResultsToShow { get; set; } = 5;
public int ActivateTimes { get; set; }
@ -227,7 +238,15 @@ namespace Flow.Launcher.Infrastructure.UserSettings
}
public bool LeaveCmdOpen { get; set; }
public bool HideWhenDeactivated { get; set; } = true;
public SearchWindowPositions SearchWindowPosition { get; set; } = SearchWindowPositions.MouseScreenCenter;
[JsonConverter(typeof(JsonStringEnumConverter))]
public SearchWindowScreens SearchWindowScreen { get; set; } = SearchWindowScreens.RememberLastLaunchLocation;
[JsonConverter(typeof(JsonStringEnumConverter))]
public SearchWindowAligns SearchWindowAlign { get; set; } = SearchWindowAligns.Center;
public int CustomScreenNumber { get; set; } = 1;
public bool IgnoreHotkeysOnFullscreen { get; set; }
public HttpProxy Proxy { get; set; } = new HttpProxy();
@ -253,12 +272,22 @@ namespace Flow.Launcher.Infrastructure.UserSettings
Light,
Dark
}
public enum SearchWindowPositions
public enum SearchWindowScreens
{
RememberLastLaunchLocation,
MouseScreenCenter,
MouseScreenCenterTop,
MouseScreenLeftTop,
MouseScreenRightTop
Cursor,
Focus,
Primary,
Custom
}
public enum SearchWindowAligns
{
Center,
CenterTop,
LeftTop,
RightTop,
Custom
}
}

View file

@ -35,25 +35,25 @@ namespace Flow.Launcher.Helper
}
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
internal static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
internal static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
internal static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
private static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
private static extern IntPtr GetShellWindow();
internal static extern IntPtr GetShellWindow();
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowRect(IntPtr hwnd, out RECT rc);
internal static extern int GetWindowRect(IntPtr hwnd, out RECT rc);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
internal static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.DLL")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

View file

@ -38,11 +38,16 @@
<system:String x:Key="hideFlowLauncherWhenLoseFocus">Hide Flow Launcher when focus is lost</system:String>
<system:String x:Key="dontPromptUpdateMsg">Do not show new version notifications</system:String>
<system:String x:Key="SearchWindowPosition">Search Window Position</system:String>
<system:String x:Key="SearchWindowPositionRememberLastLaunchLocation">Remember Last Position</system:String>
<system:String x:Key="SearchWindowPositionMouseScreenCenter">Mouse Focused Screen - Center</system:String>
<system:String x:Key="SearchWindowPositionMouseScreenCenterTop">Mouse Focused Screen - Center Top</system:String>
<system:String x:Key="SearchWindowPositionMouseScreenLeftTop">Mouse Focused Screen - Left Top</system:String>
<system:String x:Key="SearchWindowPositionMouseScreenRightTop">Mouse Focused Screen - Right Top</system:String>
<system:String x:Key="SearchWindowScreenRememberLastLaunchLocation">Remember Last Position</system:String>
<system:String x:Key="SearchWindowScreenCursor">Monitor with Mouse Cursor</system:String>
<system:String x:Key="SearchWindowScreenFocus">Monitor with Focused Window</system:String>
<system:String x:Key="SearchWindowScreenPrimary">Primary Monitor</system:String>
<system:String x:Key="SearchWindowScreenCustom">Custom Monitor</system:String>
<system:String x:Key="SearchWindowAlignCenter">Center</system:String>
<system:String x:Key="SearchWindowAlignCenterTop">Center Top</system:String>
<system:String x:Key="SearchWindowAlignLeftTop">Left Top</system:String>
<system:String x:Key="SearchWindowAlignRightTop">Right Top</system:String>
<system:String x:Key="SearchWindowAlignCustom">Custom Position</system:String>
<system:String x:Key="language">Language</system:String>
<system:String x:Key="lastQueryMode">Last Query Style</system:String>
<system:String x:Key="lastQueryModeToolTip">Show/Hide previous results when Flow Launcher is reactivated.</system:String>

View file

@ -25,6 +25,7 @@ using System.Windows.Data;
using ModernWpf.Controls;
using Key = System.Windows.Input.Key;
using System.Media;
using System.Linq;
namespace Flow.Launcher
{
@ -200,29 +201,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
{
var screen = SelectedScreen();
switch (_settings.SearchWindowAlign)
{
case SearchWindowAligns.Center:
Left = HorizonCenter(screen);
Top = VerticalCenter(screen);
break;
case SearchWindowAligns.CenterTop:
Left = HorizonCenter(screen);
Top = 10;
break;
case SearchWindowAligns.LeftTop:
Left = HorizonLeft(screen);
Top = 10;
break;
case SearchWindowAligns.RightTop:
Left = HorizonRight(screen);
Top = 10;
break;
case SearchWindowAligns.Custom:
Left = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X + _settings.CustomWindowLeft, 0).X;
Top = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y + _settings.CustomWindowTop).Y;
break;
}
}
}
private void UpdateNotifyIconText()
@ -339,8 +350,9 @@ namespace Flow.Launcher
{
_viewModel.Show();
await Task.Delay(300); // If don't give a time, Positioning will be weird.
Left = HorizonCenter();
Top = VerticalCenter();
var screen = SelectedScreen();
Left = HorizonCenter(screen);
Top = VerticalCenter(screen);
}
private void InitProgressbarAnimation()
@ -502,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;
@ -522,30 +534,62 @@ namespace Flow.Launcher
}
}
public double HorizonCenter()
public Screen SelectedScreen()
{
Screen screen = null;
switch(_settings.SearchWindowScreen)
{
case SearchWindowScreens.Cursor:
screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
break;
case SearchWindowScreens.Primary:
screen = Screen.PrimaryScreen;
break;
case SearchWindowScreens.Focus:
IntPtr foregroundWindowHandle = WindowsInteropHelper.GetForegroundWindow();
screen = Screen.FromHandle(foregroundWindowHandle);
break;
case SearchWindowScreens.Custom:
if (_settings.CustomScreenNumber <= Screen.AllScreens.Length)
screen = Screen.AllScreens[_settings.CustomScreenNumber - 1];
else
screen = Screen.AllScreens[0];
break;
default:
screen = Screen.AllScreens[0];
break;
}
return screen ?? Screen.AllScreens[0];
}
public double HorizonCenter(Screen screen)
{
var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
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;
return left;
}
public double VerticalCenter()
public double VerticalCenter(Screen screen)
{
var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
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;
return top;
}
public double HorizonRight()
public double HorizonRight(Screen screen)
{
var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
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(Screen screen)
{
var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
var left = dip1.X + 10;
return left;
}

View file

@ -693,26 +693,135 @@
</ItemsControl>
</Border>
<Border Margin="0,30,0,0" Style="{DynamicResource SettingGroupBox}">
<ItemsControl Style="{StaticResource SettingGrid}">
<StackPanel Style="{StaticResource TextPanel}">
<TextBlock Style="{DynamicResource SettingTitleLabel}" Text="{DynamicResource SearchWindowPosition}" />
</StackPanel>
<ComboBox
x:Name="SearchWindowPosition"
Grid.Column="2"
MinWidth="220"
Margin="0,0,18,0"
VerticalAlignment="Center"
DisplayMemberPath="Display"
FontSize="14"
ItemsSource="{Binding SearchWindowPositions}"
SelectedValue="{Binding Settings.SearchWindowPosition}"
SelectedValuePath="Value" />
<TextBlock Style="{StaticResource Glyph}">
&#xe7f4;
</TextBlock>
</ItemsControl>
<Border
Margin="0,30,0,0"
Padding="0"
Style="{DynamicResource SettingGroupBox}">
<StackPanel Orientation="Vertical">
<Border
Margin="0"
BorderThickness="0"
Style="{DynamicResource SettingGroupBox}">
<ItemsControl Style="{StaticResource SettingGrid}">
<StackPanel Style="{StaticResource TextPanel}">
<TextBlock Style="{DynamicResource SettingTitleLabel}" Text="{DynamicResource SearchWindowPosition}" />
</StackPanel>
<StackPanel Grid.Column="2" Orientation="Horizontal">
<ComboBox
x:Name="SearchWindowScreen"
MinWidth="220"
Margin="0,0,18,0"
VerticalAlignment="Center"
DisplayMemberPath="Display"
FontSize="14"
ItemsSource="{Binding SearchWindowScreens}"
SelectedValue="{Binding Settings.SearchWindowScreen}"
SelectedValuePath="Value" />
<ComboBox
x:Name="SelectScreen"
MinWidth="160"
Margin="0,0,18,0"
VerticalAlignment="Center"
FontSize="14"
ItemsSource="{Binding ScreenNumbers}"
SelectedValue="{Binding Settings.CustomScreenNumber}">
<ComboBox.Style>
<Style BasedOn="{StaticResource DefaultComboBoxStyle}" TargetType="ComboBox">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=SearchWindowScreen, Path=SelectedValue}" Value="{x:Static userSettings:SearchWindowScreens.Custom}">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
</ComboBox>
</StackPanel>
<TextBlock Style="{StaticResource Glyph}">
&#xe7f4;
</TextBlock>
</ItemsControl>
</Border>
<Separator
Width="Auto"
BorderThickness="1">
<Separator.Style>
<Style BasedOn="{StaticResource SettingSeparatorStyle}" TargetType="Separator">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=SearchWindowScreen, Path=SelectedValue}" Value="{x:Static userSettings:SearchWindowScreens.RememberLastLaunchLocation}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Separator.Style>
</Separator>
<Border
Margin="0"
BorderThickness="0">
<Border.Style>
<Style BasedOn="{StaticResource SettingGroupBox}" TargetType="Border">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=SearchWindowScreen, Path=SelectedValue}" Value="{x:Static userSettings:SearchWindowScreens.RememberLastLaunchLocation}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<ItemsControl Style="{StaticResource SettingGrid}">
<StackPanel Style="{StaticResource TextPanel}">
<TextBlock Style="{DynamicResource SettingTitleLabel}" Text="Search Window position on selected screen" />
</StackPanel>
<StackPanel Grid.Column="2" Orientation="Horizontal">
<ComboBox
x:Name="SearchWindowPosition"
MinWidth="160"
Margin="0,0,18,0"
VerticalAlignment="Center"
DisplayMemberPath="Display"
FontSize="14"
ItemsSource="{Binding SearchWindowAligns}"
SelectedValue="{Binding Settings.SearchWindowAlign}"
SelectedValuePath="Value">
</ComboBox>
<StackPanel Margin="0,0,18,0" Orientation="Horizontal">
<StackPanel.Style>
<Style TargetType="StackPanel">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=SearchWindowPosition, Path=SelectedValue}" Value="{x:Static userSettings:SearchWindowAligns.Custom}">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<TextBox
Height="35"
MinWidth="120"
Text="{Binding Settings.CustomWindowLeft}"
TextWrapping="NoWrap" />
<TextBlock
Margin="10"
VerticalAlignment="Center"
Foreground="{DynamicResource Color05B}"
Text="x" />
<TextBox
Height="35"
MinWidth="120"
Text="{Binding Settings.CustomWindowTop}"
TextWrapping="NoWrap" />
</StackPanel>
</StackPanel>
<TextBlock Style="{StaticResource Glyph}">
&#xe7f4;
</TextBlock>
</ItemsControl>
</Border>
</StackPanel>
</Border>
<Border Style="{DynamicResource SettingGroupBox}">

View file

@ -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<SearchWindowPosition> SearchWindowPositions
public List<SearchWindowScreen> SearchWindowScreens
{
get
{
List<SearchWindowPosition> modes = new List<SearchWindowPosition>();
var enums = (SearchWindowPositions[])Enum.GetValues(typeof(SearchWindowPositions));
List<SearchWindowScreen> modes = new List<SearchWindowScreen>();
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<SearchWindowAlign> SearchWindowAligns
{
get
{
List<SearchWindowAlign> modes = new List<SearchWindowAlign>();
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,
};
@ -489,6 +517,20 @@ namespace Flow.Launcher.ViewModel
}
}
public List<int> ScreenNumbers
{
get
{
var screens = System.Windows.Forms.Screen.AllScreens;
var screenNumbers = new List<int>();
for (int i = 1; i <= screens.Length; i++)
{
screenNumbers.Add(i);
}
return screenNumbers;
}
}
public List<string> TimeFormatList { get; } = new()
{
"h:mm",