mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-06-07 09:28:03 +08:00
[FancyZones Editor] Quick layout switch hotkeys (#10437)
Co-authored-by: Ivan Stošić <ivan100sic@gmail.com>
This commit is contained in:
parent
7ba03ed24f
commit
13c4c188fa
3
.github/actions/spell-check/expect.txt
vendored
3
.github/actions/spell-check/expect.txt
vendored
@ -714,6 +714,7 @@ finalizer
|
|||||||
findstr
|
findstr
|
||||||
FIXEDFILEINFO
|
FIXEDFILEINFO
|
||||||
FLASHZONES
|
FLASHZONES
|
||||||
|
FLASHZONESONQUICKSWITCH
|
||||||
Fle
|
Fle
|
||||||
fluentui
|
fluentui
|
||||||
flyout
|
flyout
|
||||||
@ -1685,6 +1686,7 @@ Queryable
|
|||||||
QUERYENDSESSION
|
QUERYENDSESSION
|
||||||
QUERYOPEN
|
QUERYOPEN
|
||||||
QUEUESYNC
|
QUEUESYNC
|
||||||
|
QUICKLAYOUTSWITCH
|
||||||
qwertyuiopasdfghjklzxcvbnm
|
qwertyuiopasdfghjklzxcvbnm
|
||||||
qword
|
qword
|
||||||
qwrtyuiopsghjklzxvnm
|
qwrtyuiopsghjklzxvnm
|
||||||
@ -2095,6 +2097,7 @@ Timeline
|
|||||||
timeunion
|
timeunion
|
||||||
timeutil
|
timeutil
|
||||||
titlecase
|
titlecase
|
||||||
|
TLayout
|
||||||
tlb
|
tlb
|
||||||
tlbimp
|
tlbimp
|
||||||
tmp
|
tmp
|
||||||
|
@ -284,6 +284,7 @@
|
|||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|
||||||
<Button x:Name="NewLayoutButton"
|
<Button x:Name="NewLayoutButton"
|
||||||
Click="NewLayoutButton_Click"
|
Click="NewLayoutButton_Click"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
@ -355,6 +356,7 @@
|
|||||||
PrimaryButtonClick="EditLayoutDialog_PrimaryButtonClick"
|
PrimaryButtonClick="EditLayoutDialog_PrimaryButtonClick"
|
||||||
SecondaryButtonClick="EditLayoutDialog_SecondaryButtonClick"
|
SecondaryButtonClick="EditLayoutDialog_SecondaryButtonClick"
|
||||||
Title="{x:Static props:Resources.Edit_Layout}"
|
Title="{x:Static props:Resources.Edit_Layout}"
|
||||||
|
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||||
Opened="Dialog_Opened"
|
Opened="Dialog_Opened"
|
||||||
Closed="Dialog_Closed">
|
Closed="Dialog_Closed">
|
||||||
<Grid DataContext="{Binding SelectedModel}"
|
<Grid DataContext="{Binding SelectedModel}"
|
||||||
@ -419,55 +421,55 @@
|
|||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
Visibility="{Binding Path=Type, Converter={StaticResource LayoutTypeTemplateToVisibilityConverter}}">
|
Visibility="{Binding Path=Type, Converter={StaticResource LayoutTypeTemplateToVisibilityConverter}}">
|
||||||
|
|
||||||
<Button x:Name="decrementZones"
|
<Button x:Name="decrementZones"
|
||||||
Width="40"
|
Width="40"
|
||||||
Height="40"
|
Height="40"
|
||||||
AutomationProperties.Name="{x:Static props:Resources.Zone_Count_Decrement}"
|
AutomationProperties.Name="{x:Static props:Resources.Zone_Count_Decrement}"
|
||||||
ToolTip="{x:Static props:Resources.Zone_Count_Decrement}"
|
ToolTip="{x:Static props:Resources.Zone_Count_Decrement}"
|
||||||
Foreground="{DynamicResource SystemControlBackgroundAccentBrush}"
|
Foreground="{DynamicResource SystemControlBackgroundAccentBrush}"
|
||||||
Style="{StaticResource IconOnlyButtonStyle}"
|
Style="{StaticResource IconOnlyButtonStyle}"
|
||||||
Click="DecrementZones_Click">
|
Click="DecrementZones_Click">
|
||||||
<Button.Content>
|
<Button.Content>
|
||||||
<TextBlock Text=""
|
<TextBlock Text=""
|
||||||
FontFamily="Segoe MDL2 Assets" />
|
FontFamily="Segoe MDL2 Assets" />
|
||||||
</Button.Content>
|
</Button.Content>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<TextBlock x:Name="zoneCount"
|
|
||||||
Text="{Binding TemplateZoneCount}"
|
|
||||||
FontWeight="SemiBold"
|
|
||||||
FontSize="18"
|
|
||||||
Width="32"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
TextAlignment="Center"
|
|
||||||
Margin="0,-4,0,0"
|
|
||||||
ToolTip="Number of zones"
|
|
||||||
VerticalAlignment="Center" />
|
|
||||||
|
|
||||||
<Button x:Name="incrementZones"
|
<TextBlock x:Name="zoneCount"
|
||||||
Width="40"
|
Text="{Binding TemplateZoneCount}"
|
||||||
Height="40"
|
FontWeight="SemiBold"
|
||||||
AutomationProperties.Name="{x:Static props:Resources.Zone_Count_Increment}"
|
FontSize="18"
|
||||||
ToolTip="{x:Static props:Resources.Zone_Count_Increment}"
|
Width="32"
|
||||||
Foreground="{DynamicResource SystemControlBackgroundAccentBrush}"
|
HorizontalAlignment="Center"
|
||||||
Style="{StaticResource IconOnlyButtonStyle}"
|
TextAlignment="Center"
|
||||||
Click="IncrementZones_Click">
|
Margin="0,-4,0,0"
|
||||||
<Button.Content>
|
ToolTip="Number of zones"
|
||||||
<TextBlock Text=""
|
VerticalAlignment="Center" />
|
||||||
FontFamily="Segoe MDL2 Assets" />
|
|
||||||
</Button.Content>
|
<Button x:Name="incrementZones"
|
||||||
</Button>
|
Width="40"
|
||||||
</StackPanel>
|
Height="40"
|
||||||
|
AutomationProperties.Name="{x:Static props:Resources.Zone_Count_Increment}"
|
||||||
|
ToolTip="{x:Static props:Resources.Zone_Count_Increment}"
|
||||||
|
Foreground="{DynamicResource SystemControlBackgroundAccentBrush}"
|
||||||
|
Style="{StaticResource IconOnlyButtonStyle}"
|
||||||
|
Click="IncrementZones_Click">
|
||||||
|
<Button.Content>
|
||||||
|
<TextBlock Text=""
|
||||||
|
FontFamily="Segoe MDL2 Assets" />
|
||||||
|
</Button.Content>
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
<TextBox Text="{Binding Name}"
|
<TextBox Text="{Binding Name}"
|
||||||
ui:ControlHelper.Header="{x:Static props:Resources.Name}"
|
ui:ControlHelper.Header="{x:Static props:Resources.Name}"
|
||||||
Margin="0,16,0,0"
|
Margin="0,16,2,0"
|
||||||
Visibility="{Binding IsCustom, Converter={StaticResource BooleanToVisibilityConverter}}"
|
Visibility="{Binding IsCustom, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||||
HorizontalAlignment="Stretch" />
|
HorizontalAlignment="Stretch" />
|
||||||
|
|
||||||
<CheckBox x:Name="spaceAroundSetting"
|
<CheckBox x:Name="spaceAroundSetting"
|
||||||
Content="{x:Static props:Resources.Show_Space_Zones}"
|
Content="{x:Static props:Resources.Show_Space_Zones}"
|
||||||
IsChecked="{Binding ShowSpacing}"
|
IsChecked="{Binding ShowSpacing}"
|
||||||
Margin="0,16,0,0"
|
Margin="0,16,12,0"
|
||||||
Visibility="{Binding Converter={StaticResource LayoutModelTypeToVisibilityConverter}}" />
|
Visibility="{Binding Converter={StaticResource LayoutModelTypeToVisibilityConverter}}" />
|
||||||
|
|
||||||
<ui:NumberBox Margin="0,6,0,0"
|
<ui:NumberBox Margin="0,6,0,0"
|
||||||
@ -483,7 +485,8 @@
|
|||||||
|
|
||||||
<TextBlock Text="{x:Static props:Resources.Distance_adjacent_zones}"
|
<TextBlock Text="{x:Static props:Resources.Distance_adjacent_zones}"
|
||||||
IsEnabled="{Binding ShowSpacing}"
|
IsEnabled="{Binding ShowSpacing}"
|
||||||
Margin="0,16,0,0"
|
Margin="0,16,12,0"
|
||||||
|
TextWrapping="Wrap"
|
||||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||||
x:Name="sensitivityRadiusValue" />
|
x:Name="sensitivityRadiusValue" />
|
||||||
|
|
||||||
@ -495,6 +498,18 @@
|
|||||||
SpinButtonPlacementMode="Compact"
|
SpinButtonPlacementMode="Compact"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
AutomationProperties.LabeledBy="{Binding ElementName=sensitivityRadiusValue}" />
|
AutomationProperties.LabeledBy="{Binding ElementName=sensitivityRadiusValue}" />
|
||||||
|
|
||||||
|
<TextBlock Text="{x:Static props:Resources.QuickKey_Select}"
|
||||||
|
Margin="0,16,12,0"
|
||||||
|
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Visibility="{Binding Path=Type, Converter={StaticResource LayoutTypeCustomToVisibilityConverter}}"/>
|
||||||
|
<ComboBox x:Name="quickKeySelectionComboBox"
|
||||||
|
Margin="0,6,0,0"
|
||||||
|
ItemsSource="{Binding QuickKeysAvailable}"
|
||||||
|
SelectedItem="{Binding QuickKey}"
|
||||||
|
Width="106"
|
||||||
|
Visibility="{Binding Path=Type, Converter={StaticResource LayoutTypeCustomToVisibilityConverter}}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</ui:ContentDialog>
|
</ui:ContentDialog>
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
@ -16,6 +17,8 @@ namespace FancyZonesEditor.Models
|
|||||||
{
|
{
|
||||||
_guid = Guid.NewGuid();
|
_guid = Guid.NewGuid();
|
||||||
Type = LayoutType.Custom;
|
Type = LayoutType.Custom;
|
||||||
|
|
||||||
|
MainWindowSettingsModel.QuickKeys.PropertyChanged += QuickSwitchKeys_PropertyChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected LayoutModel(string name)
|
protected LayoutModel(string name)
|
||||||
@ -48,6 +51,9 @@ namespace FancyZonesEditor.Models
|
|||||||
_isApplied = other._isApplied;
|
_isApplied = other._isApplied;
|
||||||
_sensitivityRadius = other._sensitivityRadius;
|
_sensitivityRadius = other._sensitivityRadius;
|
||||||
_zoneCount = other._zoneCount;
|
_zoneCount = other._zoneCount;
|
||||||
|
_quickKey = other._quickKey;
|
||||||
|
|
||||||
|
MainWindowSettingsModel.QuickKeys.PropertyChanged += QuickSwitchKeys_PropertyChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name - the display name for this layout model - is also used as the key in the registry
|
// Name - the display name for this layout model - is also used as the key in the registry
|
||||||
@ -158,6 +164,55 @@ namespace FancyZonesEditor.Models
|
|||||||
|
|
||||||
private int _sensitivityRadius = LayoutSettings.DefaultSensitivityRadius;
|
private int _sensitivityRadius = LayoutSettings.DefaultSensitivityRadius;
|
||||||
|
|
||||||
|
public List<string> QuickKeysAvailable
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<string> result = new List<string>();
|
||||||
|
foreach (var pair in MainWindowSettingsModel.QuickKeys.SelectedKeys)
|
||||||
|
{
|
||||||
|
if (pair.Value == string.Empty || pair.Value == Uuid)
|
||||||
|
{
|
||||||
|
result.Add(pair.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string QuickKey
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _quickKey == -1 ? Properties.Resources.Quick_Key_None : _quickKey.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
string none = Properties.Resources.Quick_Key_None;
|
||||||
|
var intValue = value == none ? -1 : int.Parse(value);
|
||||||
|
if (intValue != _quickKey)
|
||||||
|
{
|
||||||
|
string prev = _quickKey == -1 ? none : _quickKey.ToString();
|
||||||
|
_quickKey = intValue;
|
||||||
|
|
||||||
|
if (intValue != -1)
|
||||||
|
{
|
||||||
|
MainWindowSettingsModel.QuickKeys.SelectKey(value, Uuid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainWindowSettingsModel.QuickKeys.FreeKey(prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
FirePropertyChanged(nameof(QuickKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _quickKey = -1;
|
||||||
|
|
||||||
// TemplateZoneCount - number of zones selected in the picker window for template layouts
|
// TemplateZoneCount - number of zones selected in the picker window for template layouts
|
||||||
public int TemplateZoneCount
|
public int TemplateZoneCount
|
||||||
{
|
{
|
||||||
@ -200,6 +255,11 @@ namespace FancyZonesEditor.Models
|
|||||||
// Removes this Layout from the registry and the loaded CustomModels list
|
// Removes this Layout from the registry and the loaded CustomModels list
|
||||||
public void Delete()
|
public void Delete()
|
||||||
{
|
{
|
||||||
|
if (_quickKey != -1)
|
||||||
|
{
|
||||||
|
MainWindowSettingsModel.QuickKeys.FreeKey(QuickKey);
|
||||||
|
}
|
||||||
|
|
||||||
var customModels = MainWindowSettingsModel.CustomModels;
|
var customModels = MainWindowSettingsModel.CustomModels;
|
||||||
int i = customModels.IndexOf(this);
|
int i = customModels.IndexOf(this);
|
||||||
if (i != -1)
|
if (i != -1)
|
||||||
@ -241,5 +301,17 @@ namespace FancyZonesEditor.Models
|
|||||||
{
|
{
|
||||||
PersistData();
|
PersistData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void QuickSwitchKeys_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
foreach (var pair in MainWindowSettingsModel.QuickKeys.SelectedKeys)
|
||||||
|
{
|
||||||
|
if (pair.Value == Uuid)
|
||||||
|
{
|
||||||
|
QuickKey = pair.Key.ToString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ namespace FancyZonesEditor.Models
|
|||||||
{
|
{
|
||||||
public enum LayoutType
|
public enum LayoutType
|
||||||
{
|
{
|
||||||
Blank = -1,
|
Blank = 0,
|
||||||
Focus,
|
Focus,
|
||||||
Columns,
|
Columns,
|
||||||
Rows,
|
Rows,
|
||||||
|
@ -23,13 +23,6 @@ namespace FancyZonesEditor
|
|||||||
VirtualDesktopId,
|
VirtualDesktopId,
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly CanvasLayoutModel _blankModel;
|
|
||||||
private readonly CanvasLayoutModel _focusModel;
|
|
||||||
private readonly GridLayoutModel _rowsModel;
|
|
||||||
private readonly GridLayoutModel _columnsModel;
|
|
||||||
private readonly GridLayoutModel _gridModel;
|
|
||||||
private readonly GridLayoutModel _priorityGridModel;
|
|
||||||
|
|
||||||
// Non-localizable strings
|
// Non-localizable strings
|
||||||
public static readonly string RegistryPath = "SOFTWARE\\SuperFancyZones";
|
public static readonly string RegistryPath = "SOFTWARE\\SuperFancyZones";
|
||||||
public static readonly string FullRegistryPath = "HKEY_CURRENT_USER\\" + RegistryPath;
|
public static readonly string FullRegistryPath = "HKEY_CURRENT_USER\\" + RegistryPath;
|
||||||
@ -53,40 +46,40 @@ namespace FancyZonesEditor
|
|||||||
public MainWindowSettingsModel()
|
public MainWindowSettingsModel()
|
||||||
{
|
{
|
||||||
// Initialize default layout models: Blank, Focus, Columns, Rows, Grid, and PriorityGrid
|
// Initialize default layout models: Blank, Focus, Columns, Rows, Grid, and PriorityGrid
|
||||||
_blankModel = new CanvasLayoutModel(Properties.Resources.Template_Layout_Blank, LayoutType.Blank)
|
var blankModel = new CanvasLayoutModel(Properties.Resources.Template_Layout_Blank, LayoutType.Blank)
|
||||||
{
|
{
|
||||||
TemplateZoneCount = 0,
|
TemplateZoneCount = 0,
|
||||||
SensitivityRadius = 0,
|
SensitivityRadius = 0,
|
||||||
};
|
};
|
||||||
DefaultModels.Add(_blankModel);
|
DefaultModels.Insert((int)LayoutType.Blank, blankModel);
|
||||||
|
|
||||||
_focusModel = new CanvasLayoutModel(Properties.Resources.Template_Layout_Focus, LayoutType.Focus);
|
var focusModel = new CanvasLayoutModel(Properties.Resources.Template_Layout_Focus, LayoutType.Focus);
|
||||||
_focusModel.InitTemplateZones();
|
focusModel.InitTemplateZones();
|
||||||
DefaultModels.Add(_focusModel);
|
DefaultModels.Insert((int)LayoutType.Focus, focusModel);
|
||||||
|
|
||||||
_columnsModel = new GridLayoutModel(Properties.Resources.Template_Layout_Columns, LayoutType.Columns)
|
var columnsModel = new GridLayoutModel(Properties.Resources.Template_Layout_Columns, LayoutType.Columns)
|
||||||
{
|
{
|
||||||
Rows = 1,
|
Rows = 1,
|
||||||
RowPercents = new List<int>(1) { GridLayoutModel.GridMultiplier },
|
RowPercents = new List<int>(1) { GridLayoutModel.GridMultiplier },
|
||||||
};
|
};
|
||||||
_columnsModel.InitTemplateZones();
|
columnsModel.InitTemplateZones();
|
||||||
DefaultModels.Add(_columnsModel);
|
DefaultModels.Insert((int)LayoutType.Columns, columnsModel);
|
||||||
|
|
||||||
_rowsModel = new GridLayoutModel(Properties.Resources.Template_Layout_Rows, LayoutType.Rows)
|
var rowsModel = new GridLayoutModel(Properties.Resources.Template_Layout_Rows, LayoutType.Rows)
|
||||||
{
|
{
|
||||||
Columns = 1,
|
Columns = 1,
|
||||||
ColumnPercents = new List<int>(1) { GridLayoutModel.GridMultiplier },
|
ColumnPercents = new List<int>(1) { GridLayoutModel.GridMultiplier },
|
||||||
};
|
};
|
||||||
_rowsModel.InitTemplateZones();
|
rowsModel.InitTemplateZones();
|
||||||
DefaultModels.Add(_rowsModel);
|
DefaultModels.Insert((int)LayoutType.Rows, rowsModel);
|
||||||
|
|
||||||
_gridModel = new GridLayoutModel(Properties.Resources.Template_Layout_Grid, LayoutType.Grid);
|
var gridModel = new GridLayoutModel(Properties.Resources.Template_Layout_Grid, LayoutType.Grid);
|
||||||
_gridModel.InitTemplateZones();
|
gridModel.InitTemplateZones();
|
||||||
DefaultModels.Add(_gridModel);
|
DefaultModels.Insert((int)LayoutType.Grid, gridModel);
|
||||||
|
|
||||||
_priorityGridModel = new GridLayoutModel(Properties.Resources.Template_Layout_Priority_Grid, LayoutType.PriorityGrid);
|
var priorityGridModel = new GridLayoutModel(Properties.Resources.Template_Layout_Priority_Grid, LayoutType.PriorityGrid);
|
||||||
_priorityGridModel.InitTemplateZones();
|
priorityGridModel.InitTemplateZones();
|
||||||
DefaultModels.Add(_priorityGridModel);
|
DefaultModels.Insert((int)LayoutType.PriorityGrid, priorityGridModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsShiftKeyPressed - is the shift key currently being held down
|
// IsShiftKeyPressed - is the shift key currently being held down
|
||||||
@ -133,7 +126,7 @@ namespace FancyZonesEditor
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _blankModel;
|
return DefaultModels[(int)LayoutType.Blank];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,6 +142,8 @@ namespace FancyZonesEditor
|
|||||||
|
|
||||||
private static ObservableCollection<LayoutModel> _customModels = new ObservableCollection<LayoutModel>();
|
private static ObservableCollection<LayoutModel> _customModels = new ObservableCollection<LayoutModel>();
|
||||||
|
|
||||||
|
public static QuickKeysModel QuickKeys { get; } = new QuickKeysModel();
|
||||||
|
|
||||||
public LayoutModel SelectedModel
|
public LayoutModel SelectedModel
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -202,7 +197,7 @@ namespace FancyZonesEditor
|
|||||||
{
|
{
|
||||||
foreach (LayoutModel model in CustomModels)
|
foreach (LayoutModel model in CustomModels)
|
||||||
{
|
{
|
||||||
if ("{" + model.Guid.ToString().ToUpperInvariant() + "}" == currentApplied.ZonesetUuid.ToUpperInvariant())
|
if (model.Uuid == currentApplied.ZonesetUuid.ToUpperInvariant())
|
||||||
{
|
{
|
||||||
// found match
|
// found match
|
||||||
foundModel = model;
|
foundModel = model;
|
||||||
@ -234,7 +229,7 @@ namespace FancyZonesEditor
|
|||||||
|
|
||||||
if (foundModel == null)
|
if (foundModel == null)
|
||||||
{
|
{
|
||||||
foundModel = _priorityGridModel;
|
foundModel = DefaultModels[(int)LayoutType.PriorityGrid];
|
||||||
}
|
}
|
||||||
|
|
||||||
SetSelectedModel(foundModel);
|
SetSelectedModel(foundModel);
|
||||||
@ -255,6 +250,7 @@ namespace FancyZonesEditor
|
|||||||
SelectedModel.IsSelected = model.IsSelected;
|
SelectedModel.IsSelected = model.IsSelected;
|
||||||
SelectedModel.IsApplied = model.IsApplied;
|
SelectedModel.IsApplied = model.IsApplied;
|
||||||
SelectedModel.Name = model.Name;
|
SelectedModel.Name = model.Name;
|
||||||
|
SelectedModel.QuickKey = model.QuickKey;
|
||||||
|
|
||||||
if (model is GridLayoutModel grid)
|
if (model is GridLayoutModel grid)
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace FancyZonesEditor.Models
|
||||||
|
{
|
||||||
|
public class QuickKeysModel : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
public SortedDictionary<string, string> SelectedKeys { get; } = new SortedDictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ Properties.Resources.Quick_Key_None, string.Empty },
|
||||||
|
{ "0", string.Empty },
|
||||||
|
{ "1", string.Empty },
|
||||||
|
{ "2", string.Empty },
|
||||||
|
{ "3", string.Empty },
|
||||||
|
{ "4", string.Empty },
|
||||||
|
{ "5", string.Empty },
|
||||||
|
{ "6", string.Empty },
|
||||||
|
{ "7", string.Empty },
|
||||||
|
{ "8", string.Empty },
|
||||||
|
{ "9", string.Empty },
|
||||||
|
};
|
||||||
|
|
||||||
|
public QuickKeysModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
public void FreeKey(string key)
|
||||||
|
{
|
||||||
|
if (SelectedKeys.ContainsKey(key))
|
||||||
|
{
|
||||||
|
SelectedKeys[key] = string.Empty;
|
||||||
|
FirePropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SelectKey(string key, string uuid)
|
||||||
|
{
|
||||||
|
if (!SelectedKeys.ContainsKey(key))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SelectedKeys[key] == uuid)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean previous value
|
||||||
|
foreach (var pair in SelectedKeys)
|
||||||
|
{
|
||||||
|
if (pair.Value == uuid)
|
||||||
|
{
|
||||||
|
SelectedKeys[pair.Key] = string.Empty;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectedKeys[key] = uuid;
|
||||||
|
FirePropertyChanged();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CleanUp()
|
||||||
|
{
|
||||||
|
var keys = SelectedKeys.Keys.ToList();
|
||||||
|
foreach (var key in keys)
|
||||||
|
{
|
||||||
|
SelectedKeys[key] = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
FirePropertyChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void FirePropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -555,6 +555,24 @@ namespace FancyZonesEditor.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to None.
|
||||||
|
/// </summary>
|
||||||
|
public static string Quick_Key_None {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Quick_Key_None", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Select a key to quickly apply the layout (Win + Ctrl + Alt + key).
|
||||||
|
/// </summary>
|
||||||
|
public static string QuickKey_Select {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("QuickKey_Select", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Reset layout.
|
/// Looks up a localized string similar to Reset layout.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -346,4 +346,10 @@
|
|||||||
<value>Splitter:</value>
|
<value>Splitter:</value>
|
||||||
<comment>Title for concept: A segmenter visual for splitting one item into two. This would be the vertical line</comment>
|
<comment>Title for concept: A segmenter visual for splitting one item into two. This would be the vertical line</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="QuickKey_Select" xml:space="preserve">
|
||||||
|
<value>Select a key to quickly apply the layout (Win + Ctrl + Alt + key)</value>
|
||||||
|
</data>
|
||||||
|
<data name="Quick_Key_None" xml:space="preserve">
|
||||||
|
<value>None</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -57,6 +57,7 @@ namespace FancyZonesEditor.Utils
|
|||||||
MonitorTop,
|
MonitorTop,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parsing cmd args
|
||||||
private struct NativeMonitorData
|
private struct NativeMonitorData
|
||||||
{
|
{
|
||||||
public string MonitorId { get; set; }
|
public string MonitorId { get; set; }
|
||||||
@ -87,6 +88,7 @@ namespace FancyZonesEditor.Utils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// zones-settings: devices
|
||||||
private struct DeviceWrapper
|
private struct DeviceWrapper
|
||||||
{
|
{
|
||||||
public struct ActiveZoneSetWrapper
|
public struct ActiveZoneSetWrapper
|
||||||
@ -109,6 +111,7 @@ namespace FancyZonesEditor.Utils
|
|||||||
public int EditorSensitivityRadius { get; set; }
|
public int EditorSensitivityRadius { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// zones-settings: custom-zone-sets
|
||||||
private class CanvasInfoWrapper
|
private class CanvasInfoWrapper
|
||||||
{
|
{
|
||||||
public struct CanvasZoneWrapper
|
public struct CanvasZoneWrapper
|
||||||
@ -131,6 +134,7 @@ namespace FancyZonesEditor.Utils
|
|||||||
public int SensitivityRadius { get; set; } = LayoutSettings.DefaultSensitivityRadius;
|
public int SensitivityRadius { get; set; } = LayoutSettings.DefaultSensitivityRadius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// zones-settings: custom-zone-sets
|
||||||
private class GridInfoWrapper
|
private class GridInfoWrapper
|
||||||
{
|
{
|
||||||
public int Rows { get; set; }
|
public int Rows { get; set; }
|
||||||
@ -150,6 +154,7 @@ namespace FancyZonesEditor.Utils
|
|||||||
public int SensitivityRadius { get; set; } = LayoutSettings.DefaultSensitivityRadius;
|
public int SensitivityRadius { get; set; } = LayoutSettings.DefaultSensitivityRadius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// zones-settings: custom-zone-sets
|
||||||
private struct CustomLayoutWrapper
|
private struct CustomLayoutWrapper
|
||||||
{
|
{
|
||||||
public string Uuid { get; set; }
|
public string Uuid { get; set; }
|
||||||
@ -161,6 +166,7 @@ namespace FancyZonesEditor.Utils
|
|||||||
public JsonElement Info { get; set; } // CanvasInfoWrapper or GridInfoWrapper
|
public JsonElement Info { get; set; } // CanvasInfoWrapper or GridInfoWrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// zones-settings: templates
|
||||||
private struct TemplateLayoutWrapper
|
private struct TemplateLayoutWrapper
|
||||||
{
|
{
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
@ -174,6 +180,15 @@ namespace FancyZonesEditor.Utils
|
|||||||
public int SensitivityRadius { get; set; }
|
public int SensitivityRadius { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// zones-settings: quick-layout-keys-wrapper
|
||||||
|
private struct QuickLayoutKeysWrapper
|
||||||
|
{
|
||||||
|
public int Key { get; set; }
|
||||||
|
|
||||||
|
public string Uuid { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// zones-settings
|
||||||
private struct ZoneSettingsWrapper
|
private struct ZoneSettingsWrapper
|
||||||
{
|
{
|
||||||
public List<DeviceWrapper> Devices { get; set; }
|
public List<DeviceWrapper> Devices { get; set; }
|
||||||
@ -181,6 +196,8 @@ namespace FancyZonesEditor.Utils
|
|||||||
public List<CustomLayoutWrapper> CustomZoneSets { get; set; }
|
public List<CustomLayoutWrapper> CustomZoneSets { get; set; }
|
||||||
|
|
||||||
public List<TemplateLayoutWrapper> Templates { get; set; }
|
public List<TemplateLayoutWrapper> Templates { get; set; }
|
||||||
|
|
||||||
|
public List<QuickLayoutKeysWrapper> QuickLayoutKeys { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct EditorParams
|
private struct EditorParams
|
||||||
@ -528,6 +545,7 @@ namespace FancyZonesEditor.Utils
|
|||||||
bool devicesParsingResult = SetDevices(zoneSettings.Devices);
|
bool devicesParsingResult = SetDevices(zoneSettings.Devices);
|
||||||
bool customZonesParsingResult = SetCustomLayouts(zoneSettings.CustomZoneSets);
|
bool customZonesParsingResult = SetCustomLayouts(zoneSettings.CustomZoneSets);
|
||||||
bool templatesParsingResult = SetTemplateLayouts(zoneSettings.Templates);
|
bool templatesParsingResult = SetTemplateLayouts(zoneSettings.Templates);
|
||||||
|
bool quickLayoutSwitchKeysParsingResult = SetQuickLayoutSwitchKeys(zoneSettings.QuickLayoutKeys);
|
||||||
|
|
||||||
if (!devicesParsingResult || !customZonesParsingResult)
|
if (!devicesParsingResult || !customZonesParsingResult)
|
||||||
{
|
{
|
||||||
@ -549,6 +567,7 @@ namespace FancyZonesEditor.Utils
|
|||||||
zoneSettings.Devices = new List<DeviceWrapper>();
|
zoneSettings.Devices = new List<DeviceWrapper>();
|
||||||
zoneSettings.CustomZoneSets = new List<CustomLayoutWrapper>();
|
zoneSettings.CustomZoneSets = new List<CustomLayoutWrapper>();
|
||||||
zoneSettings.Templates = new List<TemplateLayoutWrapper>();
|
zoneSettings.Templates = new List<TemplateLayoutWrapper>();
|
||||||
|
zoneSettings.QuickLayoutKeys = new List<QuickLayoutKeysWrapper>();
|
||||||
|
|
||||||
// Serialize used devices
|
// Serialize used devices
|
||||||
foreach (var monitor in App.Overlay.Monitors)
|
foreach (var monitor in App.Overlay.Monitors)
|
||||||
@ -685,6 +704,27 @@ namespace FancyZonesEditor.Utils
|
|||||||
zoneSettings.Templates.Add(wrapper);
|
zoneSettings.Templates.Add(wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Serialize quick layout switch keys
|
||||||
|
foreach (var pair in MainWindowSettingsModel.QuickKeys.SelectedKeys)
|
||||||
|
{
|
||||||
|
if (pair.Value != string.Empty)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
QuickLayoutKeysWrapper wrapper = new QuickLayoutKeysWrapper
|
||||||
|
{
|
||||||
|
Key = int.Parse(pair.Key),
|
||||||
|
Uuid = pair.Value,
|
||||||
|
};
|
||||||
|
|
||||||
|
zoneSettings.QuickLayoutKeys.Add(wrapper);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string jsonString = JsonSerializer.Serialize(zoneSettings, _options);
|
string jsonString = JsonSerializer.Serialize(zoneSettings, _options);
|
||||||
@ -781,7 +821,15 @@ namespace FancyZonesEditor.Utils
|
|||||||
zones.Add(new Int32Rect { X = (int)zone.X, Y = (int)zone.Y, Width = (int)zone.Width, Height = (int)zone.Height });
|
zones.Add(new Int32Rect { X = (int)zone.X, Y = (int)zone.Y, Width = (int)zone.Width, Height = (int)zone.Height });
|
||||||
}
|
}
|
||||||
|
|
||||||
layout = new CanvasLayoutModel(zoneSet.Uuid, zoneSet.Name, LayoutType.Custom, zones, info.RefWidth, info.RefHeight);
|
try
|
||||||
|
{
|
||||||
|
layout = new CanvasLayoutModel(zoneSet.Uuid, zoneSet.Name, LayoutType.Custom, zones, info.RefWidth, info.RefHeight);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
layout.SensitivityRadius = info.SensitivityRadius;
|
layout.SensitivityRadius = info.SensitivityRadius;
|
||||||
}
|
}
|
||||||
else if (zoneSet.Type == GridLayoutModel.ModelTypeID)
|
else if (zoneSet.Type == GridLayoutModel.ModelTypeID)
|
||||||
@ -797,7 +845,15 @@ namespace FancyZonesEditor.Utils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
layout = new GridLayoutModel(zoneSet.Uuid, zoneSet.Name, LayoutType.Custom, info.Rows, info.Columns, info.RowsPercentage, info.ColumnsPercentage, cells);
|
try
|
||||||
|
{
|
||||||
|
layout = new GridLayoutModel(zoneSet.Uuid, zoneSet.Name, LayoutType.Custom, info.Rows, info.Columns, info.RowsPercentage, info.ColumnsPercentage, cells);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
layout.SensitivityRadius = info.SensitivityRadius;
|
layout.SensitivityRadius = info.SensitivityRadius;
|
||||||
(layout as GridLayoutModel).ShowSpacing = info.ShowSpacing;
|
(layout as GridLayoutModel).ShowSpacing = info.ShowSpacing;
|
||||||
(layout as GridLayoutModel).Spacing = info.Spacing;
|
(layout as GridLayoutModel).Spacing = info.Spacing;
|
||||||
@ -823,24 +879,35 @@ namespace FancyZonesEditor.Utils
|
|||||||
|
|
||||||
foreach (var wrapper in templateLayouts)
|
foreach (var wrapper in templateLayouts)
|
||||||
{
|
{
|
||||||
var type = JsonTagToLayoutType(wrapper.Type);
|
LayoutType type = JsonTagToLayoutType(wrapper.Type);
|
||||||
|
LayoutModel layout = MainWindowSettingsModel.DefaultModels[(int)type];
|
||||||
|
|
||||||
foreach (var layout in MainWindowSettingsModel.DefaultModels)
|
layout.SensitivityRadius = wrapper.SensitivityRadius;
|
||||||
|
layout.TemplateZoneCount = wrapper.ZoneCount;
|
||||||
|
|
||||||
|
if (layout is GridLayoutModel grid)
|
||||||
{
|
{
|
||||||
if (layout.Type == type)
|
grid.ShowSpacing = wrapper.ShowSpacing;
|
||||||
{
|
grid.Spacing = wrapper.Spacing;
|
||||||
layout.SensitivityRadius = wrapper.SensitivityRadius;
|
|
||||||
layout.TemplateZoneCount = wrapper.ZoneCount;
|
|
||||||
|
|
||||||
if (layout is GridLayoutModel grid)
|
|
||||||
{
|
|
||||||
grid.ShowSpacing = wrapper.ShowSpacing;
|
|
||||||
grid.Spacing = wrapper.Spacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
layout.InitTemplateZones();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
layout.InitTemplateZones();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SetQuickLayoutSwitchKeys(List<QuickLayoutKeysWrapper> quickSwitchKeys)
|
||||||
|
{
|
||||||
|
if (quickSwitchKeys == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindowSettingsModel.QuickKeys.CleanUp();
|
||||||
|
foreach (var wrapper in quickSwitchKeys)
|
||||||
|
{
|
||||||
|
MainWindowSettingsModel.QuickKeys.SelectKey(wrapper.Key.ToString(), wrapper.Uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -34,6 +34,30 @@ enum class DisplayChangeType
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
constexpr int CUSTOM_POSITIONING_LEFT_TOP_PADDING = 16;
|
constexpr int CUSTOM_POSITIONING_LEFT_TOP_PADDING = 16;
|
||||||
|
|
||||||
|
struct require_read_lock
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
require_read_lock(const std::shared_lock<T>& lock)
|
||||||
|
{
|
||||||
|
lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
require_read_lock(const std::unique_lock<T>& lock)
|
||||||
|
{
|
||||||
|
lock;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct require_write_lock
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
require_write_lock(const std::unique_lock<T>& lock)
|
||||||
|
{
|
||||||
|
lock;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-localizable strings
|
// Non-localizable strings
|
||||||
@ -184,40 +208,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
LRESULT WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
|
LRESULT WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
|
||||||
void OnDisplayChange(DisplayChangeType changeType) noexcept;
|
void OnDisplayChange(DisplayChangeType changeType, require_write_lock) noexcept;
|
||||||
void AddZoneWindow(HMONITOR monitor, const std::wstring& deviceId) noexcept;
|
void AddZoneWindow(HMONITOR monitor, const std::wstring& deviceId, require_write_lock) noexcept;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static LRESULT CALLBACK s_WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
|
static LRESULT CALLBACK s_WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct require_read_lock
|
|
||||||
{
|
|
||||||
template<typename T>
|
|
||||||
require_read_lock(const std::shared_lock<T>& lock)
|
|
||||||
{
|
|
||||||
lock;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
void UpdateZoneWindows(require_write_lock) noexcept;
|
||||||
require_read_lock(const std::unique_lock<T>& lock)
|
void UpdateWindowsPositions(require_write_lock) noexcept;
|
||||||
{
|
|
||||||
lock;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct require_write_lock
|
|
||||||
{
|
|
||||||
template<typename T>
|
|
||||||
require_write_lock(const std::unique_lock<T>& lock)
|
|
||||||
{
|
|
||||||
lock;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void UpdateZoneWindows() noexcept;
|
|
||||||
void UpdateWindowsPositions() noexcept;
|
|
||||||
void CycleActiveZoneSet(DWORD vkCode) noexcept;
|
|
||||||
bool OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexcept;
|
bool OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexcept;
|
||||||
bool OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept;
|
bool OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept;
|
||||||
bool OnSnapHotkey(DWORD vkCode) noexcept;
|
bool OnSnapHotkey(DWORD vkCode) noexcept;
|
||||||
@ -232,12 +232,15 @@ private:
|
|||||||
std::pair<winrt::com_ptr<IZoneWindow>, std::vector<size_t>> GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, bool isPrimaryMonitor) noexcept;
|
std::pair<winrt::com_ptr<IZoneWindow>, std::vector<size_t>> GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, bool isPrimaryMonitor) noexcept;
|
||||||
void MoveWindowIntoZone(HWND window, winrt::com_ptr<IZoneWindow> zoneWindow, const std::vector<size_t>& zoneIndexSet) noexcept;
|
void MoveWindowIntoZone(HWND window, winrt::com_ptr<IZoneWindow> zoneWindow, const std::vector<size_t>& zoneIndexSet) noexcept;
|
||||||
|
|
||||||
void OnEditorExitEvent() noexcept;
|
void OnEditorExitEvent(require_write_lock) noexcept;
|
||||||
void UpdateZoneSets() noexcept;
|
void UpdateZoneSets(require_write_lock) noexcept;
|
||||||
bool ShouldProcessSnapHotkey(DWORD vkCode) noexcept;
|
bool ShouldProcessSnapHotkey(DWORD vkCode) noexcept;
|
||||||
|
void ApplyQuickLayout(int key) noexcept;
|
||||||
|
void FlashZones(require_write_lock) noexcept;
|
||||||
|
|
||||||
std::vector<std::pair<HMONITOR, RECT>> GetRawMonitorData() noexcept;
|
std::vector<std::pair<HMONITOR, RECT>> GetRawMonitorData() noexcept;
|
||||||
std::vector<HMONITOR> GetMonitorsSorted() noexcept;
|
std::vector<HMONITOR> GetMonitorsSorted() noexcept;
|
||||||
|
HMONITOR WorkAreaKeyFromWindow(HWND window) noexcept;
|
||||||
|
|
||||||
const HINSTANCE m_hinstance{};
|
const HINSTANCE m_hinstance{};
|
||||||
|
|
||||||
@ -266,6 +269,7 @@ private:
|
|||||||
static UINT WM_PRIV_FILE_UPDATE; // Scheduled when the a watched file is updated
|
static UINT WM_PRIV_FILE_UPDATE; // Scheduled when the a watched file is updated
|
||||||
|
|
||||||
static UINT WM_PRIV_SNAP_HOTKEY; // Scheduled when we receive a snap hotkey key down press
|
static UINT WM_PRIV_SNAP_HOTKEY; // Scheduled when we receive a snap hotkey key down press
|
||||||
|
static UINT WM_PRIV_QUICK_LAYOUT_KEY; // Scheduled when we receive a key down press to quickly apply a layout
|
||||||
|
|
||||||
// Did we terminate the editor or was it closed cleanly?
|
// Did we terminate the editor or was it closed cleanly?
|
||||||
enum class EditorExitKind : byte
|
enum class EditorExitKind : byte
|
||||||
@ -283,6 +287,7 @@ UINT FancyZones::WM_PRIV_VD_UPDATE = RegisterWindowMessage(L"{b8b72b46-f42f-4c26
|
|||||||
UINT FancyZones::WM_PRIV_EDITOR = RegisterWindowMessage(L"{87543824-7080-4e91-9d9c-0404642fc7b6}");
|
UINT FancyZones::WM_PRIV_EDITOR = RegisterWindowMessage(L"{87543824-7080-4e91-9d9c-0404642fc7b6}");
|
||||||
UINT FancyZones::WM_PRIV_FILE_UPDATE = RegisterWindowMessage(L"{632f17a9-55a7-45f1-a4db-162e39271d92}");
|
UINT FancyZones::WM_PRIV_FILE_UPDATE = RegisterWindowMessage(L"{632f17a9-55a7-45f1-a4db-162e39271d92}");
|
||||||
UINT FancyZones::WM_PRIV_SNAP_HOTKEY = RegisterWindowMessage(L"{763c03a3-03d9-4cde-8d71-f0358b0b4b52}");
|
UINT FancyZones::WM_PRIV_SNAP_HOTKEY = RegisterWindowMessage(L"{763c03a3-03d9-4cde-8d71-f0358b0b4b52}");
|
||||||
|
UINT FancyZones::WM_PRIV_QUICK_LAYOUT_KEY = RegisterWindowMessage(L"{72f4fd8e-23f1-43ab-bbbc-029363df9a84}");
|
||||||
|
|
||||||
// IFancyZones
|
// IFancyZones
|
||||||
IFACEMETHODIMP_(void)
|
IFACEMETHODIMP_(void)
|
||||||
@ -553,18 +558,6 @@ FancyZones::OnKeyDown(PKBDLLHOOKSTRUCT info) noexcept
|
|||||||
bool const ctrl = GetAsyncKeyState(VK_CONTROL) & 0x8000;
|
bool const ctrl = GetAsyncKeyState(VK_CONTROL) & 0x8000;
|
||||||
if ((win && !shift && !ctrl) || (win && ctrl && alt))
|
if ((win && !shift && !ctrl) || (win && ctrl && alt))
|
||||||
{
|
{
|
||||||
// Temporarily disable Win+Ctrl+Number functionality
|
|
||||||
// if (ctrl)
|
|
||||||
// {
|
|
||||||
// if ((info->vkCode >= '0') && (info->vkCode <= '9'))
|
|
||||||
// {
|
|
||||||
// // Win+Ctrl+Number will cycle through ZoneSets
|
|
||||||
// Trace::FancyZones::OnKeyDown(info->vkCode, win, ctrl, false /*inMoveSize*/);
|
|
||||||
// CycleActiveZoneSet(info->vkCode);
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
if ((info->vkCode == VK_RIGHT) || (info->vkCode == VK_LEFT) || (info->vkCode == VK_UP) || (info->vkCode == VK_DOWN))
|
if ((info->vkCode == VK_RIGHT) || (info->vkCode == VK_LEFT) || (info->vkCode == VK_UP) || (info->vkCode == VK_DOWN))
|
||||||
{
|
{
|
||||||
if (ShouldProcessSnapHotkey(info->vkCode))
|
if (ShouldProcessSnapHotkey(info->vkCode))
|
||||||
@ -576,14 +569,34 @@ FancyZones::OnKeyDown(PKBDLLHOOKSTRUCT info) noexcept
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Temporarily disable Win+Ctrl+Number functionality
|
|
||||||
//else if (m_inMoveSize && (info->vkCode >= '0') && (info->vkCode <= '9'))
|
if (m_settings->GetSettings()->quickLayoutSwitch)
|
||||||
//{
|
{
|
||||||
// // This allows you to cycle through ZoneSets while dragging a window
|
int digitPressed = -1;
|
||||||
// Trace::FancyZones::OnKeyDown(info->vkCode, win, false /*control*/, true /*inMoveSize*/);
|
if ('0' <= info->vkCode && info->vkCode <= '9')
|
||||||
// CycleActiveZoneSet(info->vkCode);
|
{
|
||||||
// return false;
|
digitPressed = info->vkCode - '0';
|
||||||
//}
|
}
|
||||||
|
else if (VK_NUMPAD0 <= info->vkCode && info->vkCode <= VK_NUMPAD9)
|
||||||
|
{
|
||||||
|
digitPressed = info->vkCode - VK_NUMPAD0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dragging = m_windowMoveHandler.InMoveSize();
|
||||||
|
bool changeLayoutWhileNotDragging = !dragging && !shift && win && ctrl && alt && digitPressed != -1;
|
||||||
|
bool changeLayoutWhileDragging = dragging && digitPressed != -1;
|
||||||
|
|
||||||
|
if (changeLayoutWhileNotDragging || changeLayoutWhileDragging)
|
||||||
|
{
|
||||||
|
auto quickKeysMap = FancyZonesDataInstance().GetLayoutQuickKeys();
|
||||||
|
if (std::any_of(quickKeysMap.begin(), quickKeysMap.end(), [=](auto item) { return item.second == digitPressed; }))
|
||||||
|
{
|
||||||
|
PostMessageW(m_window, WM_PRIV_QUICK_LAYOUT_KEY, 0, static_cast<LPARAM>(digitPressed));
|
||||||
|
Trace::FancyZones::QuickLayoutSwitched(changeLayoutWhileNotDragging);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_windowMoveHandler.IsDragEnabled() && shift)
|
if (m_windowMoveHandler.IsDragEnabled() && shift)
|
||||||
{
|
{
|
||||||
@ -755,13 +768,16 @@ void FancyZones::ToggleEditor() noexcept
|
|||||||
|
|
||||||
void FancyZones::SettingsChanged() noexcept
|
void FancyZones::SettingsChanged() noexcept
|
||||||
{
|
{
|
||||||
|
_TRACER_;
|
||||||
|
std::unique_lock writeLock(m_lock);
|
||||||
|
|
||||||
// Update the hotkey
|
// Update the hotkey
|
||||||
UnregisterHotKey(m_window, 1);
|
UnregisterHotKey(m_window, 1);
|
||||||
RegisterHotKey(m_window, 1, m_settings->GetSettings()->editorHotkey.get_modifiers(), m_settings->GetSettings()->editorHotkey.get_code());
|
RegisterHotKey(m_window, 1, m_settings->GetSettings()->editorHotkey.get_modifiers(), m_settings->GetSettings()->editorHotkey.get_code());
|
||||||
|
|
||||||
// Needed if we toggled spanZonesAcrossMonitors
|
// Needed if we toggled spanZonesAcrossMonitors
|
||||||
m_workAreaHandler.Clear();
|
m_workAreaHandler.Clear();
|
||||||
OnDisplayChange(DisplayChangeType::Initialization);
|
OnDisplayChange(DisplayChangeType::Initialization, writeLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IZoneWindowHost
|
// IZoneWindowHost
|
||||||
@ -770,7 +786,8 @@ FancyZones::MoveWindowsOnActiveZoneSetChange() noexcept
|
|||||||
{
|
{
|
||||||
if (m_settings->GetSettings()->zoneSetChange_moveWindows)
|
if (m_settings->GetSettings()->zoneSetChange_moveWindows)
|
||||||
{
|
{
|
||||||
UpdateWindowsPositions();
|
std::unique_lock writeLock(m_lock);
|
||||||
|
UpdateWindowsPositions(writeLock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -793,8 +810,9 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
|||||||
{
|
{
|
||||||
// Changes in taskbar position resulted in different size of work area.
|
// Changes in taskbar position resulted in different size of work area.
|
||||||
// Invalidate cached work-areas so they can be recreated with latest information.
|
// Invalidate cached work-areas so they can be recreated with latest information.
|
||||||
|
std::unique_lock writeLock(m_lock);
|
||||||
m_workAreaHandler.Clear();
|
m_workAreaHandler.Clear();
|
||||||
OnDisplayChange(DisplayChangeType::WorkArea);
|
OnDisplayChange(DisplayChangeType::WorkArea, writeLock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -802,8 +820,9 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
|||||||
case WM_DISPLAYCHANGE:
|
case WM_DISPLAYCHANGE:
|
||||||
{
|
{
|
||||||
// Display resolution changed. Invalidate cached work-areas so they can be recreated with latest information.
|
// Display resolution changed. Invalidate cached work-areas so they can be recreated with latest information.
|
||||||
|
std::unique_lock writeLock(m_lock);
|
||||||
m_workAreaHandler.Clear();
|
m_workAreaHandler.Clear();
|
||||||
OnDisplayChange(DisplayChangeType::DisplayChange);
|
OnDisplayChange(DisplayChangeType::DisplayChange, writeLock);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -818,11 +837,13 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
|||||||
}
|
}
|
||||||
else if (message == WM_PRIV_VD_INIT)
|
else if (message == WM_PRIV_VD_INIT)
|
||||||
{
|
{
|
||||||
OnDisplayChange(DisplayChangeType::Initialization);
|
std::unique_lock writeLock(m_lock);
|
||||||
|
OnDisplayChange(DisplayChangeType::Initialization, writeLock);
|
||||||
}
|
}
|
||||||
else if (message == WM_PRIV_VD_SWITCH)
|
else if (message == WM_PRIV_VD_SWITCH)
|
||||||
{
|
{
|
||||||
OnDisplayChange(DisplayChangeType::VirtualDesktop);
|
std::unique_lock writeLock(m_lock);
|
||||||
|
OnDisplayChange(DisplayChangeType::VirtualDesktop, writeLock);
|
||||||
}
|
}
|
||||||
else if (message == WM_PRIV_VD_UPDATE)
|
else if (message == WM_PRIV_VD_UPDATE)
|
||||||
{
|
{
|
||||||
@ -836,7 +857,8 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
|||||||
{
|
{
|
||||||
if (lparam == static_cast<LPARAM>(EditorExitKind::Exit))
|
if (lparam == static_cast<LPARAM>(EditorExitKind::Exit))
|
||||||
{
|
{
|
||||||
OnEditorExitEvent();
|
std::unique_lock writeLock(m_lock);
|
||||||
|
OnEditorExitEvent(writeLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -873,7 +895,12 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
|||||||
else if (message == WM_PRIV_FILE_UPDATE)
|
else if (message == WM_PRIV_FILE_UPDATE)
|
||||||
{
|
{
|
||||||
FancyZonesDataInstance().LoadFancyZonesData();
|
FancyZonesDataInstance().LoadFancyZonesData();
|
||||||
UpdateZoneSets();
|
std::unique_lock writeLock(m_lock);
|
||||||
|
UpdateZoneSets(writeLock);
|
||||||
|
}
|
||||||
|
else if (message == WM_PRIV_QUICK_LAYOUT_KEY)
|
||||||
|
{
|
||||||
|
ApplyQuickLayout(static_cast<int>(lparam));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -885,7 +912,7 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
|
void FancyZones::OnDisplayChange(DisplayChangeType changeType, require_write_lock lock) noexcept
|
||||||
{
|
{
|
||||||
_TRACER_;
|
_TRACER_;
|
||||||
if (changeType == DisplayChangeType::VirtualDesktop ||
|
if (changeType == DisplayChangeType::VirtualDesktop ||
|
||||||
@ -912,22 +939,20 @@ void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateZoneWindows();
|
UpdateZoneWindows(lock);
|
||||||
|
|
||||||
if ((changeType == DisplayChangeType::WorkArea) || (changeType == DisplayChangeType::DisplayChange))
|
if ((changeType == DisplayChangeType::WorkArea) || (changeType == DisplayChangeType::DisplayChange))
|
||||||
{
|
{
|
||||||
if (m_settings->GetSettings()->displayChange_moveWindows)
|
if (m_settings->GetSettings()->displayChange_moveWindows)
|
||||||
{
|
{
|
||||||
UpdateWindowsPositions();
|
UpdateWindowsPositions(lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FancyZones::AddZoneWindow(HMONITOR monitor, const std::wstring& deviceId) noexcept
|
void FancyZones::AddZoneWindow(HMONITOR monitor, const std::wstring& deviceId, require_write_lock) noexcept
|
||||||
{
|
{
|
||||||
_TRACER_;
|
_TRACER_;
|
||||||
std::unique_lock writeLock(m_lock);
|
|
||||||
|
|
||||||
if (m_workAreaHandler.IsNewWorkArea(m_currentDesktopId, monitor))
|
if (m_workAreaHandler.IsNewWorkArea(m_currentDesktopId, monitor))
|
||||||
{
|
{
|
||||||
wil::unique_cotaskmem_string virtualDesktopId;
|
wil::unique_cotaskmem_string virtualDesktopId;
|
||||||
@ -974,7 +999,7 @@ LRESULT CALLBACK FancyZones::s_WndProc(HWND window, UINT message, WPARAM wparam,
|
|||||||
DefWindowProc(window, message, wparam, lparam);
|
DefWindowProc(window, message, wparam, lparam);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FancyZones::UpdateZoneWindows() noexcept
|
void FancyZones::UpdateZoneWindows(require_write_lock lock) noexcept
|
||||||
{
|
{
|
||||||
// Mapping between display device name and device index (operating system identifies each display device with an index value).
|
// Mapping between display device name and device index (operating system identifies each display device with an index value).
|
||||||
std::unordered_map<std::wstring, DWORD> displayDeviceIdxMap;
|
std::unordered_map<std::wstring, DWORD> displayDeviceIdxMap;
|
||||||
@ -982,6 +1007,7 @@ void FancyZones::UpdateZoneWindows() noexcept
|
|||||||
{
|
{
|
||||||
FancyZones* fancyZones;
|
FancyZones* fancyZones;
|
||||||
std::unordered_map<std::wstring, DWORD>* displayDeviceIdx;
|
std::unordered_map<std::wstring, DWORD>* displayDeviceIdx;
|
||||||
|
require_write_lock lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto callback = [](HMONITOR monitor, HDC, RECT*, LPARAM data) -> BOOL {
|
auto callback = [](HMONITOR monitor, HDC, RECT*, LPARAM data) -> BOOL {
|
||||||
@ -993,27 +1019,25 @@ void FancyZones::UpdateZoneWindows() noexcept
|
|||||||
FancyZones* fancyZones = params->fancyZones;
|
FancyZones* fancyZones = params->fancyZones;
|
||||||
|
|
||||||
std::wstring deviceId = FancyZonesUtils::GetDisplayDeviceId(mi.szDevice, displayDeviceIdxMap);
|
std::wstring deviceId = FancyZonesUtils::GetDisplayDeviceId(mi.szDevice, displayDeviceIdxMap);
|
||||||
fancyZones->AddZoneWindow(monitor, deviceId);
|
fancyZones->AddZoneWindow(monitor, deviceId, params->lock);
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (m_settings->GetSettings()->spanZonesAcrossMonitors)
|
if (m_settings->GetSettings()->spanZonesAcrossMonitors)
|
||||||
{
|
{
|
||||||
AddZoneWindow(nullptr, {});
|
AddZoneWindow(nullptr, {}, lock);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
capture capture{ this, &displayDeviceIdxMap };
|
capture capture{ this, &displayDeviceIdxMap, lock };
|
||||||
EnumDisplayMonitors(nullptr, nullptr, callback, reinterpret_cast<LPARAM>(&capture));
|
EnumDisplayMonitors(nullptr, nullptr, callback, reinterpret_cast<LPARAM>(&capture));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FancyZones::UpdateWindowsPositions() noexcept
|
void FancyZones::UpdateWindowsPositions(require_write_lock) noexcept
|
||||||
{
|
{
|
||||||
_TRACER_;
|
|
||||||
auto callback = [](HWND window, LPARAM data) -> BOOL {
|
auto callback = [](HWND window, LPARAM data) -> BOOL {
|
||||||
_TRACER_;
|
|
||||||
size_t bitmask = reinterpret_cast<size_t>(::GetProp(window, ZonedWindowProperties::PropertyMultipleZoneID));
|
size_t bitmask = reinterpret_cast<size_t>(::GetProp(window, ZonedWindowProperties::PropertyMultipleZoneID));
|
||||||
|
|
||||||
if (bitmask != 0)
|
if (bitmask != 0)
|
||||||
@ -1028,7 +1052,6 @@ void FancyZones::UpdateWindowsPositions() noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto strongThis = reinterpret_cast<FancyZones*>(data);
|
auto strongThis = reinterpret_cast<FancyZones*>(data);
|
||||||
std::unique_lock writeLock(strongThis->m_lock);
|
|
||||||
auto zoneWindow = strongThis->m_workAreaHandler.GetWorkArea(window);
|
auto zoneWindow = strongThis->m_workAreaHandler.GetWorkArea(window);
|
||||||
if (zoneWindow)
|
if (zoneWindow)
|
||||||
{
|
{
|
||||||
@ -1040,39 +1063,10 @@ void FancyZones::UpdateWindowsPositions() noexcept
|
|||||||
EnumWindows(callback, reinterpret_cast<LPARAM>(this));
|
EnumWindows(callback, reinterpret_cast<LPARAM>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FancyZones::CycleActiveZoneSet(DWORD vkCode) noexcept
|
|
||||||
{
|
|
||||||
_TRACER_;
|
|
||||||
auto window = GetForegroundWindow();
|
|
||||||
if (FancyZonesUtils::IsCandidateForZoning(window, m_settings->GetSettings()->excludedAppsArray))
|
|
||||||
{
|
|
||||||
const HMONITOR monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
|
|
||||||
if (monitor)
|
|
||||||
{
|
|
||||||
std::shared_lock readLock(m_lock);
|
|
||||||
|
|
||||||
auto zoneWindow = m_workAreaHandler.GetWorkArea(m_currentDesktopId, monitor);
|
|
||||||
if (zoneWindow)
|
|
||||||
{
|
|
||||||
zoneWindow->CycleActiveZoneSet(vkCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FancyZones::OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexcept
|
bool FancyZones::OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexcept
|
||||||
{
|
{
|
||||||
_TRACER_;
|
_TRACER_;
|
||||||
HMONITOR current;
|
HMONITOR current = WorkAreaKeyFromWindow(window);
|
||||||
|
|
||||||
if (m_settings->GetSettings()->spanZonesAcrossMonitors)
|
|
||||||
{
|
|
||||||
current = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
current = MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<HMONITOR> monitorInfo = GetMonitorsSorted();
|
std::vector<HMONITOR> monitorInfo = GetMonitorsSorted();
|
||||||
if (current && monitorInfo.size() > 1 && m_settings->GetSettings()->moveWindowAcrossMonitors)
|
if (current && monitorInfo.size() > 1 && m_settings->GetSettings()->moveWindowAcrossMonitors)
|
||||||
@ -1130,16 +1124,7 @@ bool FancyZones::OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexce
|
|||||||
|
|
||||||
bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
|
bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
|
||||||
{
|
{
|
||||||
HMONITOR current;
|
HMONITOR current = WorkAreaKeyFromWindow(window);
|
||||||
|
|
||||||
if (m_settings->GetSettings()->spanZonesAcrossMonitors)
|
|
||||||
{
|
|
||||||
current = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
current = MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto allMonitors = FancyZonesUtils::GetAllMonitorRects<&MONITORINFOEX::rcWork>();
|
auto allMonitors = FancyZonesUtils::GetAllMonitorRects<&MONITORINFOEX::rcWork>();
|
||||||
|
|
||||||
@ -1316,14 +1301,14 @@ bool FancyZones::IsSplashScreen(HWND window)
|
|||||||
return wcscmp(NonLocalizable::SplashClassName, className) == 0;
|
return wcscmp(NonLocalizable::SplashClassName, className) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FancyZones::OnEditorExitEvent() noexcept
|
void FancyZones::OnEditorExitEvent(require_write_lock lock) noexcept
|
||||||
{
|
{
|
||||||
// Collect information about changes in zone layout after editor exited.
|
// Collect information about changes in zone layout after editor exited.
|
||||||
FancyZonesDataInstance().LoadFancyZonesData();
|
FancyZonesDataInstance().LoadFancyZonesData();
|
||||||
UpdateZoneSets();
|
UpdateZoneSets(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FancyZones::UpdateZoneSets() noexcept
|
void FancyZones::UpdateZoneSets(require_write_lock lock) noexcept
|
||||||
{
|
{
|
||||||
for (auto workArea : m_workAreaHandler.GetAllWorkAreas())
|
for (auto workArea : m_workAreaHandler.GetAllWorkAreas())
|
||||||
{
|
{
|
||||||
@ -1331,7 +1316,7 @@ void FancyZones::UpdateZoneSets() noexcept
|
|||||||
}
|
}
|
||||||
if (m_settings->GetSettings()->zoneSetChange_moveWindows)
|
if (m_settings->GetSettings()->zoneSetChange_moveWindows)
|
||||||
{
|
{
|
||||||
UpdateWindowsPositions();
|
UpdateWindowsPositions(lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1340,15 +1325,7 @@ bool FancyZones::ShouldProcessSnapHotkey(DWORD vkCode) noexcept
|
|||||||
auto window = GetForegroundWindow();
|
auto window = GetForegroundWindow();
|
||||||
if (m_settings->GetSettings()->overrideSnapHotkeys && FancyZonesUtils::IsCandidateForZoning(window, m_settings->GetSettings()->excludedAppsArray))
|
if (m_settings->GetSettings()->overrideSnapHotkeys && FancyZonesUtils::IsCandidateForZoning(window, m_settings->GetSettings()->excludedAppsArray))
|
||||||
{
|
{
|
||||||
HMONITOR monitor;
|
HMONITOR monitor = WorkAreaKeyFromWindow(window);
|
||||||
if (m_settings->GetSettings()->spanZonesAcrossMonitors)
|
|
||||||
{
|
|
||||||
monitor = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto zoneWindow = m_workAreaHandler.GetWorkArea(m_currentDesktopId, monitor);
|
auto zoneWindow = m_workAreaHandler.GetWorkArea(m_currentDesktopId, monitor);
|
||||||
if (zoneWindow && zoneWindow->ActiveZoneSet() && zoneWindow->ActiveZoneSet()->LayoutType() != FancyZonesDataTypes::ZoneSetLayoutType::Blank)
|
if (zoneWindow && zoneWindow->ActiveZoneSet() && zoneWindow->ActiveZoneSet()->LayoutType() != FancyZonesDataTypes::ZoneSetLayoutType::Blank)
|
||||||
@ -1366,6 +1343,47 @@ bool FancyZones::ShouldProcessSnapHotkey(DWORD vkCode) noexcept
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FancyZones::ApplyQuickLayout(int key) noexcept
|
||||||
|
{
|
||||||
|
std::unique_lock writeLock(m_lock);
|
||||||
|
|
||||||
|
std::wstring uuid;
|
||||||
|
for (auto [zoneUuid, hotkey] : FancyZonesDataInstance().GetLayoutQuickKeys())
|
||||||
|
{
|
||||||
|
if (hotkey == key)
|
||||||
|
{
|
||||||
|
uuid = zoneUuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto workArea = m_workAreaHandler.GetWorkAreaFromCursor(m_currentDesktopId);
|
||||||
|
|
||||||
|
// Find a custom zone set with this uuid and apply it
|
||||||
|
auto customZoneSets = FancyZonesDataInstance().GetCustomZoneSetsMap();
|
||||||
|
|
||||||
|
if (!customZoneSets.contains(uuid))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FancyZonesDataTypes::ZoneSetData data{ .uuid = uuid, .type = FancyZonesDataTypes::ZoneSetLayoutType::Custom };
|
||||||
|
FancyZonesDataInstance().SetActiveZoneSet(workArea->UniqueId(), data);
|
||||||
|
FancyZonesDataInstance().SaveZoneSettings();
|
||||||
|
UpdateZoneSets(writeLock);
|
||||||
|
FlashZones(writeLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FancyZones::FlashZones(require_write_lock) noexcept
|
||||||
|
{
|
||||||
|
if (m_settings->GetSettings()->flashZonesOnQuickSwitch && !m_windowMoveHandler.IsDragEnabled())
|
||||||
|
{
|
||||||
|
for (auto [monitor, workArea] : m_workAreaHandler.GetWorkAreasByDesktopId(m_currentDesktopId))
|
||||||
|
{
|
||||||
|
workArea->FlashZones();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<HMONITOR> FancyZones::GetMonitorsSorted() noexcept
|
std::vector<HMONITOR> FancyZones::GetMonitorsSorted() noexcept
|
||||||
{
|
{
|
||||||
std::shared_lock readLock(m_lock);
|
std::shared_lock readLock(m_lock);
|
||||||
@ -1397,6 +1415,18 @@ std::vector<std::pair<HMONITOR, RECT>> FancyZones::GetRawMonitorData() noexcept
|
|||||||
return monitorInfo;
|
return monitorInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HMONITOR FancyZones::WorkAreaKeyFromWindow(HWND window) noexcept
|
||||||
|
{
|
||||||
|
if (m_settings->GetSettings()->spanZonesAcrossMonitors)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
winrt::com_ptr<IFancyZones> MakeFancyZones(HINSTANCE hinstance,
|
winrt::com_ptr<IFancyZones> MakeFancyZones(HINSTANCE hinstance,
|
||||||
const winrt::com_ptr<IFancyZonesSettings>& settings,
|
const winrt::com_ptr<IFancyZonesSettings>& settings,
|
||||||
std::function<void()> disableCallback) noexcept
|
std::function<void()> disableCallback) noexcept
|
||||||
|
@ -511,10 +511,33 @@ bool FancyZonesData::SetAppLastZones(HWND window, const std::wstring& deviceId,
|
|||||||
void FancyZonesData::SetActiveZoneSet(const std::wstring& deviceId, const FancyZonesDataTypes::ZoneSetData& data)
|
void FancyZonesData::SetActiveZoneSet(const std::wstring& deviceId, const FancyZonesDataTypes::ZoneSetData& data)
|
||||||
{
|
{
|
||||||
std::scoped_lock lock{ dataLock };
|
std::scoped_lock lock{ dataLock };
|
||||||
auto it = deviceInfoMap.find(deviceId);
|
|
||||||
if (it != deviceInfoMap.end())
|
auto deviceIt = deviceInfoMap.find(deviceId);
|
||||||
|
if (deviceIt == deviceInfoMap.end())
|
||||||
{
|
{
|
||||||
it->second.activeZoneSet = data;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceIt->second.activeZoneSet = data;
|
||||||
|
|
||||||
|
// If the zone set is custom, we need to copy its properties to the device
|
||||||
|
auto zonesetIt = customZoneSetsMap.find(data.uuid);
|
||||||
|
if (zonesetIt != customZoneSetsMap.end())
|
||||||
|
{
|
||||||
|
if (zonesetIt->second.type == FancyZonesDataTypes::CustomLayoutType::Grid)
|
||||||
|
{
|
||||||
|
auto layoutInfo = std::get<FancyZonesDataTypes::GridLayoutInfo>(zonesetIt->second.info);
|
||||||
|
deviceIt->second.sensitivityRadius = layoutInfo.sensitivityRadius();
|
||||||
|
deviceIt->second.showSpacing = layoutInfo.showSpacing();
|
||||||
|
deviceIt->second.spacing = layoutInfo.spacing();
|
||||||
|
deviceIt->second.zoneCount = layoutInfo.zoneCount();
|
||||||
|
}
|
||||||
|
else if (zonesetIt->second.type == FancyZonesDataTypes::CustomLayoutType::Canvas)
|
||||||
|
{
|
||||||
|
auto layoutInfo = std::get<FancyZonesDataTypes::CanvasLayoutInfo>(zonesetIt->second.info);
|
||||||
|
deviceIt->second.sensitivityRadius = layoutInfo.sensitivityRadius;
|
||||||
|
deviceIt->second.zoneCount = (int)layoutInfo.zones.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -536,6 +559,7 @@ void FancyZonesData::LoadFancyZonesData()
|
|||||||
appZoneHistoryMap = JSONHelpers::ParseAppZoneHistory(fancyZonesDataJSON);
|
appZoneHistoryMap = JSONHelpers::ParseAppZoneHistory(fancyZonesDataJSON);
|
||||||
deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
|
deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
|
||||||
customZoneSetsMap = JSONHelpers::ParseCustomZoneSets(fancyZonesDataJSON);
|
customZoneSetsMap = JSONHelpers::ParseCustomZoneSets(fancyZonesDataJSON);
|
||||||
|
quickKeysMap = JSONHelpers::ParseQuickKeys(fancyZonesDataJSON);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,7 +573,7 @@ void FancyZonesData::SaveZoneSettings() const
|
|||||||
{
|
{
|
||||||
_TRACER_;
|
_TRACER_;
|
||||||
std::scoped_lock lock{ dataLock };
|
std::scoped_lock lock{ dataLock };
|
||||||
JSONHelpers::SaveZoneSettings(zonesSettingsFileName, deviceInfoMap, customZoneSetsMap);
|
JSONHelpers::SaveZoneSettings(zonesSettingsFileName, deviceInfoMap, customZoneSetsMap, quickKeysMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FancyZonesData::SaveAppZoneHistory() const
|
void FancyZonesData::SaveAppZoneHistory() const
|
||||||
|
@ -48,6 +48,12 @@ public:
|
|||||||
|
|
||||||
const std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>>& GetAppZoneHistoryMap() const;
|
const std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>>& GetAppZoneHistoryMap() const;
|
||||||
|
|
||||||
|
inline const JSONHelpers::TLayoutQuickKeysMap& GetLayoutQuickKeys() const
|
||||||
|
{
|
||||||
|
std::scoped_lock lock{ dataLock };
|
||||||
|
return quickKeysMap;
|
||||||
|
}
|
||||||
|
|
||||||
inline const std::wstring& GetZonesSettingsFileName() const
|
inline const std::wstring& GetZonesSettingsFileName() const
|
||||||
{
|
{
|
||||||
return zonesSettingsFileName;
|
return zonesSettingsFileName;
|
||||||
@ -121,6 +127,8 @@ private:
|
|||||||
JSONHelpers::TDeviceInfoMap deviceInfoMap{};
|
JSONHelpers::TDeviceInfoMap deviceInfoMap{};
|
||||||
// Maps custom zoneset UUID to it's data
|
// Maps custom zoneset UUID to it's data
|
||||||
JSONHelpers::TCustomZoneSetsMap customZoneSetsMap{};
|
JSONHelpers::TCustomZoneSetsMap customZoneSetsMap{};
|
||||||
|
// Maps zoneset UUID with quick access keys
|
||||||
|
JSONHelpers::TLayoutQuickKeysMap quickKeysMap{};
|
||||||
|
|
||||||
std::wstring zonesSettingsFileName;
|
std::wstring zonesSettingsFileName;
|
||||||
std::wstring appZoneHistoryFileName;
|
std::wstring appZoneHistoryFileName;
|
||||||
|
@ -112,4 +112,18 @@ namespace FancyZonesDataTypes
|
|||||||
cellRow.resize(m_columns, 0);
|
cellRow.resize(m_columns, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GridLayoutInfo::zoneCount() const
|
||||||
|
{
|
||||||
|
int high = 0;
|
||||||
|
for (const auto& row : m_cellChildMap)
|
||||||
|
{
|
||||||
|
for (int val : row)
|
||||||
|
{
|
||||||
|
high = max(high, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return high + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,8 @@ namespace FancyZonesDataTypes
|
|||||||
inline int spacing() const { return m_spacing; }
|
inline int spacing() const { return m_spacing; }
|
||||||
inline int sensitivityRadius() const { return m_sensitivityRadius; }
|
inline int sensitivityRadius() const { return m_sensitivityRadius; }
|
||||||
|
|
||||||
|
int zoneCount() const;
|
||||||
|
|
||||||
int m_rows;
|
int m_rows;
|
||||||
int m_columns;
|
int m_columns;
|
||||||
std::vector<int> m_rowsPercents;
|
std::vector<int> m_rowsPercents;
|
||||||
|
@ -35,6 +35,9 @@ namespace NonLocalizable
|
|||||||
const wchar_t HistoryStr[] = L"history";
|
const wchar_t HistoryStr[] = L"history";
|
||||||
const wchar_t InfoStr[] = L"info";
|
const wchar_t InfoStr[] = L"info";
|
||||||
const wchar_t NameStr[] = L"name";
|
const wchar_t NameStr[] = L"name";
|
||||||
|
const wchar_t QuickAccessKey[] = L"key";
|
||||||
|
const wchar_t QuickAccessUuid[] = L"uuid";
|
||||||
|
const wchar_t QuickLayoutKeys[] = L"quick-layout-keys";
|
||||||
const wchar_t RefHeightStr[] = L"ref-height";
|
const wchar_t RefHeightStr[] = L"ref-height";
|
||||||
const wchar_t RefWidthStr[] = L"ref-width";
|
const wchar_t RefWidthStr[] = L"ref-width";
|
||||||
const wchar_t RowsPercentageStr[] = L"rows-percentage";
|
const wchar_t RowsPercentageStr[] = L"rows-percentage";
|
||||||
@ -471,6 +474,38 @@ namespace JSONHelpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
json::JsonObject LayoutQuickKeyJSON::ToJson(const LayoutQuickKeyJSON& layoutQuickKey)
|
||||||
|
{
|
||||||
|
json::JsonObject result{};
|
||||||
|
|
||||||
|
result.SetNamedValue(NonLocalizable::QuickAccessUuid, json::value(layoutQuickKey.layoutUuid));
|
||||||
|
result.SetNamedValue(NonLocalizable::QuickAccessKey, json::value(layoutQuickKey.key));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<LayoutQuickKeyJSON> LayoutQuickKeyJSON::FromJson(const json::JsonObject& layoutQuickKey)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LayoutQuickKeyJSON result;
|
||||||
|
|
||||||
|
result.layoutUuid = layoutQuickKey.GetNamedString(NonLocalizable::QuickAccessUuid);
|
||||||
|
if (!FancyZonesUtils::IsValidGuid(result.layoutUuid))
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.key = static_cast<int>(layoutQuickKey.GetNamedNumber(NonLocalizable::QuickAccessKey));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (const winrt::hresult_error&)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
json::JsonObject MonitorInfo::ToJson(const MonitorInfo& monitor)
|
json::JsonObject MonitorInfo::ToJson(const MonitorInfo& monitor)
|
||||||
{
|
{
|
||||||
json::JsonObject result{};
|
json::JsonObject result{};
|
||||||
@ -527,7 +562,7 @@ namespace JSONHelpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap, const TCustomZoneSetsMap& customZoneSetsMap)
|
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap, const TCustomZoneSetsMap& customZoneSetsMap, const TLayoutQuickKeysMap& quickKeysMap)
|
||||||
{
|
{
|
||||||
auto before = json::from_file(zonesSettingsFileName);
|
auto before = json::from_file(zonesSettingsFileName);
|
||||||
|
|
||||||
@ -549,6 +584,7 @@ namespace JSONHelpers
|
|||||||
root.SetNamedValue(NonLocalizable::DevicesStr, JSONHelpers::SerializeDeviceInfos(deviceInfoMap));
|
root.SetNamedValue(NonLocalizable::DevicesStr, JSONHelpers::SerializeDeviceInfos(deviceInfoMap));
|
||||||
root.SetNamedValue(NonLocalizable::CustomZoneSetsStr, JSONHelpers::SerializeCustomZoneSets(customZoneSetsMap));
|
root.SetNamedValue(NonLocalizable::CustomZoneSetsStr, JSONHelpers::SerializeCustomZoneSets(customZoneSetsMap));
|
||||||
root.SetNamedValue(NonLocalizable::Templates, templates);
|
root.SetNamedValue(NonLocalizable::Templates, templates);
|
||||||
|
root.SetNamedValue(NonLocalizable::QuickLayoutKeys, JSONHelpers::SerializeQuickKeys(quickKeysMap));
|
||||||
|
|
||||||
if (!before.has_value() || before.value().Stringify() != root.Stringify())
|
if (!before.has_value() || before.value().Stringify() != root.Stringify())
|
||||||
{
|
{
|
||||||
@ -675,4 +711,40 @@ namespace JSONHelpers
|
|||||||
|
|
||||||
return customZoneSetsJSON;
|
return customZoneSetsJSON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TLayoutQuickKeysMap ParseQuickKeys(const json::JsonObject& fancyZonesDataJSON)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TLayoutQuickKeysMap quickKeysMap{};
|
||||||
|
auto quickKeys = fancyZonesDataJSON.GetNamedArray(NonLocalizable::QuickLayoutKeys);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < quickKeys.Size(); ++i)
|
||||||
|
{
|
||||||
|
if (auto quickKey = LayoutQuickKeyJSON::FromJson(quickKeys.GetObjectAt(i)); quickKey.has_value())
|
||||||
|
{
|
||||||
|
quickKeysMap[quickKey->layoutUuid] = std::move(quickKey->key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(quickKeysMap);
|
||||||
|
}
|
||||||
|
catch (const winrt::hresult_error& e)
|
||||||
|
{
|
||||||
|
Logger::error(L"Parsing quick keys error: {}", e.message());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json::JsonArray SerializeQuickKeys(const TLayoutQuickKeysMap& quickKeysMap)
|
||||||
|
{
|
||||||
|
json::JsonArray quickKeysJSON{};
|
||||||
|
|
||||||
|
for (const auto& [uuid, key] : quickKeysMap)
|
||||||
|
{
|
||||||
|
quickKeysJSON.Append(LayoutQuickKeyJSON::ToJson(LayoutQuickKeyJSON{ uuid, key }));
|
||||||
|
}
|
||||||
|
|
||||||
|
return quickKeysJSON;
|
||||||
|
}
|
||||||
}
|
}
|
@ -55,9 +55,19 @@ namespace JSONHelpers
|
|||||||
static std::optional<DeviceInfoJSON> FromJson(const json::JsonObject& device);
|
static std::optional<DeviceInfoJSON> FromJson(const json::JsonObject& device);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LayoutQuickKeyJSON
|
||||||
|
{
|
||||||
|
std::wstring layoutUuid;
|
||||||
|
int key;
|
||||||
|
|
||||||
|
static json::JsonObject ToJson(const LayoutQuickKeyJSON& device);
|
||||||
|
static std::optional<LayoutQuickKeyJSON> FromJson(const json::JsonObject& device);
|
||||||
|
};
|
||||||
|
|
||||||
using TAppZoneHistoryMap = std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>>;
|
using TAppZoneHistoryMap = std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>>;
|
||||||
using TDeviceInfoMap = std::unordered_map<std::wstring, FancyZonesDataTypes::DeviceInfoData>;
|
using TDeviceInfoMap = std::unordered_map<std::wstring, FancyZonesDataTypes::DeviceInfoData>;
|
||||||
using TCustomZoneSetsMap = std::unordered_map<std::wstring, FancyZonesDataTypes::CustomZoneSetData>;
|
using TCustomZoneSetsMap = std::unordered_map<std::wstring, FancyZonesDataTypes::CustomZoneSetData>;
|
||||||
|
using TLayoutQuickKeysMap = std::unordered_map<std::wstring, int>;
|
||||||
|
|
||||||
struct MonitorInfo
|
struct MonitorInfo
|
||||||
{
|
{
|
||||||
@ -81,7 +91,7 @@ namespace JSONHelpers
|
|||||||
|
|
||||||
json::JsonObject GetPersistFancyZonesJSON(const std::wstring& zonesSettingsFileName, const std::wstring& appZoneHistoryFileName);
|
json::JsonObject GetPersistFancyZonesJSON(const std::wstring& zonesSettingsFileName, const std::wstring& appZoneHistoryFileName);
|
||||||
|
|
||||||
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap, const TCustomZoneSetsMap& customZoneSetsMap);
|
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap, const TCustomZoneSetsMap& customZoneSetsMap, const TLayoutQuickKeysMap& quickKeysMap);
|
||||||
void SaveAppZoneHistory(const std::wstring& appZoneHistoryFileName, const TAppZoneHistoryMap& appZoneHistoryMap);
|
void SaveAppZoneHistory(const std::wstring& appZoneHistoryFileName, const TAppZoneHistoryMap& appZoneHistoryMap);
|
||||||
|
|
||||||
TAppZoneHistoryMap ParseAppZoneHistory(const json::JsonObject& fancyZonesDataJSON);
|
TAppZoneHistoryMap ParseAppZoneHistory(const json::JsonObject& fancyZonesDataJSON);
|
||||||
@ -92,4 +102,7 @@ namespace JSONHelpers
|
|||||||
|
|
||||||
TCustomZoneSetsMap ParseCustomZoneSets(const json::JsonObject& fancyZonesDataJSON);
|
TCustomZoneSetsMap ParseCustomZoneSets(const json::JsonObject& fancyZonesDataJSON);
|
||||||
json::JsonArray SerializeCustomZoneSets(const TCustomZoneSetsMap& customZoneSetsMap);
|
json::JsonArray SerializeCustomZoneSets(const TCustomZoneSetsMap& customZoneSetsMap);
|
||||||
|
|
||||||
|
TLayoutQuickKeysMap ParseQuickKeys(const json::JsonObject& fancyZonesDataJSON);
|
||||||
|
json::JsonArray SerializeQuickKeys(const TLayoutQuickKeysMap& quickKeysMap);
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,27 @@ winrt::com_ptr<IZoneWindow> MonitorWorkAreaHandler::GetWorkArea(const GUID& desk
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
winrt::com_ptr<IZoneWindow> MonitorWorkAreaHandler::GetWorkAreaFromCursor(const GUID& desktopId)
|
||||||
|
{
|
||||||
|
auto allMonitorsWorkArea = GetWorkArea(desktopId, NULL);
|
||||||
|
if (allMonitorsWorkArea)
|
||||||
|
{
|
||||||
|
// First, check if there's a work area spanning all monitors (signalled by the NULL monitor handle)
|
||||||
|
return allMonitorsWorkArea;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Otherwise, look for the work area based on cursor position
|
||||||
|
POINT cursorPoint;
|
||||||
|
if (!GetCursorPos(&cursorPoint))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetWorkArea(desktopId, MonitorFromPoint(cursorPoint, MONITOR_DEFAULTTONULL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
winrt::com_ptr<IZoneWindow> MonitorWorkAreaHandler::GetWorkArea(HWND window)
|
winrt::com_ptr<IZoneWindow> MonitorWorkAreaHandler::GetWorkArea(HWND window)
|
||||||
{
|
{
|
||||||
GUID desktopId{};
|
GUID desktopId{};
|
||||||
|
@ -29,6 +29,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
winrt::com_ptr<IZoneWindow> GetWorkArea(const GUID& desktopId, HMONITOR monitor);
|
winrt::com_ptr<IZoneWindow> GetWorkArea(const GUID& desktopId, HMONITOR monitor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get work area based on virtual desktop id and the current cursor position.
|
||||||
|
*
|
||||||
|
* @param[in] desktopId Virtual desktop identifier.
|
||||||
|
*
|
||||||
|
* @returns Object representing single work area, interface to all actions available on work area
|
||||||
|
* (e.g. moving windows through zone layout specified for that work area).
|
||||||
|
*/
|
||||||
|
winrt::com_ptr<IZoneWindow> GetWorkAreaFromCursor(const GUID& desktopId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get work area on which specified window is located.
|
* Get work area on which specified window is located.
|
||||||
*
|
*
|
||||||
|
@ -247,4 +247,10 @@
|
|||||||
<value>Failed to save the FancyZones settings. Please retry again later, if the problem persists report the bug to</value>
|
<value>Failed to save the FancyZones settings. Please retry again later, if the problem persists report the bug to</value>
|
||||||
<comment>"Report bug to" will have a URL after. FancyZone is a product name, keep as is.</comment>
|
<comment>"Report bug to" will have a URL after. FancyZone is a product name, keep as is.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Setting_Description_QuickLayoutSwitch" xml:space="preserve">
|
||||||
|
<value>Enable quick layout switch</value>
|
||||||
|
</data>
|
||||||
|
<data name="Setting_Description_FlashZonesOnQuickSwitch" xml:space="preserve">
|
||||||
|
<value>Flash zones when switching layout</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -21,6 +21,8 @@ namespace NonLocalizable
|
|||||||
const wchar_t AppLastZoneMoveWindowsID[] = L"fancyzones_appLastZone_moveWindows";
|
const wchar_t AppLastZoneMoveWindowsID[] = L"fancyzones_appLastZone_moveWindows";
|
||||||
const wchar_t OpenWindowOnActiveMonitorID[] = L"fancyzones_openWindowOnActiveMonitor";
|
const wchar_t OpenWindowOnActiveMonitorID[] = L"fancyzones_openWindowOnActiveMonitor";
|
||||||
const wchar_t RestoreSizeID[] = L"fancyzones_restoreSize";
|
const wchar_t RestoreSizeID[] = L"fancyzones_restoreSize";
|
||||||
|
const wchar_t QuickLayoutSwitch[] = L"fancyzones_quickLayoutSwitch";
|
||||||
|
const wchar_t FlashZonesOnQuickSwitch[] = L"fancyzones_flashZonesOnQuickSwitch";
|
||||||
const wchar_t UseCursorPosEditorStartupScreenID[] = L"use_cursorpos_editor_startupscreen";
|
const wchar_t UseCursorPosEditorStartupScreenID[] = L"use_cursorpos_editor_startupscreen";
|
||||||
const wchar_t ShowOnAllMonitorsID[] = L"fancyzones_show_on_all_monitors";
|
const wchar_t ShowOnAllMonitorsID[] = L"fancyzones_show_on_all_monitors";
|
||||||
const wchar_t SpanZonesAcrossMonitorsID[] = L"fancyzones_span_zones_across_monitors";
|
const wchar_t SpanZonesAcrossMonitorsID[] = L"fancyzones_span_zones_across_monitors";
|
||||||
@ -80,7 +82,7 @@ private:
|
|||||||
PCWSTR name;
|
PCWSTR name;
|
||||||
bool* value;
|
bool* value;
|
||||||
int resourceId;
|
int resourceId;
|
||||||
} m_configBools[14] = {
|
} m_configBools[16] = {
|
||||||
{ NonLocalizable::ShiftDragID, &m_settings.shiftDrag, IDS_SETTING_DESCRIPTION_SHIFTDRAG },
|
{ NonLocalizable::ShiftDragID, &m_settings.shiftDrag, IDS_SETTING_DESCRIPTION_SHIFTDRAG },
|
||||||
{ NonLocalizable::MouseSwitchID, &m_settings.mouseSwitch, IDS_SETTING_DESCRIPTION_MOUSESWITCH },
|
{ NonLocalizable::MouseSwitchID, &m_settings.mouseSwitch, IDS_SETTING_DESCRIPTION_MOUSESWITCH },
|
||||||
{ NonLocalizable::OverrideSnapHotKeysID, &m_settings.overrideSnapHotkeys, IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS },
|
{ NonLocalizable::OverrideSnapHotKeysID, &m_settings.overrideSnapHotkeys, IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS },
|
||||||
@ -91,6 +93,8 @@ private:
|
|||||||
{ NonLocalizable::AppLastZoneMoveWindowsID, &m_settings.appLastZone_moveWindows, IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS },
|
{ NonLocalizable::AppLastZoneMoveWindowsID, &m_settings.appLastZone_moveWindows, IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS },
|
||||||
{ NonLocalizable::OpenWindowOnActiveMonitorID, &m_settings.openWindowOnActiveMonitor, IDS_SETTING_DESCRIPTION_OPEN_WINDOW_ON_ACTIVE_MONITOR },
|
{ NonLocalizable::OpenWindowOnActiveMonitorID, &m_settings.openWindowOnActiveMonitor, IDS_SETTING_DESCRIPTION_OPEN_WINDOW_ON_ACTIVE_MONITOR },
|
||||||
{ NonLocalizable::RestoreSizeID, &m_settings.restoreSize, IDS_SETTING_DESCRIPTION_RESTORESIZE },
|
{ NonLocalizable::RestoreSizeID, &m_settings.restoreSize, IDS_SETTING_DESCRIPTION_RESTORESIZE },
|
||||||
|
{ NonLocalizable::QuickLayoutSwitch, &m_settings.quickLayoutSwitch, IDS_SETTING_DESCRIPTION_QUICKLAYOUTSWITCH },
|
||||||
|
{ NonLocalizable::FlashZonesOnQuickSwitch, &m_settings.flashZonesOnQuickSwitch, IDS_SETTING_DESCRIPTION_FLASHZONESONQUICKSWITCH },
|
||||||
{ NonLocalizable::UseCursorPosEditorStartupScreenID, &m_settings.use_cursorpos_editor_startupscreen, IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN },
|
{ NonLocalizable::UseCursorPosEditorStartupScreenID, &m_settings.use_cursorpos_editor_startupscreen, IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN },
|
||||||
{ NonLocalizable::ShowOnAllMonitorsID, &m_settings.showZonesOnAllMonitors, IDS_SETTING_DESCRIPTION_SHOW_FANCY_ZONES_ON_ALL_MONITORS },
|
{ NonLocalizable::ShowOnAllMonitorsID, &m_settings.showZonesOnAllMonitors, IDS_SETTING_DESCRIPTION_SHOW_FANCY_ZONES_ON_ALL_MONITORS },
|
||||||
{ NonLocalizable::SpanZonesAcrossMonitorsID, &m_settings.spanZonesAcrossMonitors, IDS_SETTING_DESCRIPTION_SPAN_ZONES_ACROSS_MONITORS },
|
{ NonLocalizable::SpanZonesAcrossMonitorsID, &m_settings.spanZonesAcrossMonitors, IDS_SETTING_DESCRIPTION_SPAN_ZONES_ACROSS_MONITORS },
|
||||||
|
@ -34,6 +34,8 @@ struct Settings
|
|||||||
bool appLastZone_moveWindows = false;
|
bool appLastZone_moveWindows = false;
|
||||||
bool openWindowOnActiveMonitor = false;
|
bool openWindowOnActiveMonitor = false;
|
||||||
bool restoreSize = false;
|
bool restoreSize = false;
|
||||||
|
bool quickLayoutSwitch = true;
|
||||||
|
bool flashZonesOnQuickSwitch = true;
|
||||||
bool use_cursorpos_editor_startupscreen = true;
|
bool use_cursorpos_editor_startupscreen = true;
|
||||||
bool showZonesOnAllMonitors = false;
|
bool showZonesOnAllMonitors = false;
|
||||||
bool spanZonesAcrossMonitors = false;
|
bool spanZonesAcrossMonitors = false;
|
||||||
|
@ -124,8 +124,6 @@ public:
|
|||||||
MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle) noexcept;
|
MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle) noexcept;
|
||||||
IFACEMETHODIMP_(bool)
|
IFACEMETHODIMP_(bool)
|
||||||
ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode) noexcept;
|
ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode) noexcept;
|
||||||
IFACEMETHODIMP_(void)
|
|
||||||
CycleActiveZoneSet(DWORD vkCode) noexcept;
|
|
||||||
IFACEMETHODIMP_(std::wstring)
|
IFACEMETHODIMP_(std::wstring)
|
||||||
UniqueId() noexcept { return { m_uniqueId }; }
|
UniqueId() noexcept { return { m_uniqueId }; }
|
||||||
IFACEMETHODIMP_(void)
|
IFACEMETHODIMP_(void)
|
||||||
@ -140,6 +138,8 @@ public:
|
|||||||
UpdateActiveZoneSet() noexcept;
|
UpdateActiveZoneSet() noexcept;
|
||||||
IFACEMETHODIMP_(void)
|
IFACEMETHODIMP_(void)
|
||||||
ClearSelectedZones() noexcept;
|
ClearSelectedZones() noexcept;
|
||||||
|
IFACEMETHODIMP_(void)
|
||||||
|
FlashZones() noexcept;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static LRESULT CALLBACK s_WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) noexcept;
|
static LRESULT CALLBACK s_WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) noexcept;
|
||||||
@ -149,9 +149,8 @@ private:
|
|||||||
void CalculateZoneSet() noexcept;
|
void CalculateZoneSet() noexcept;
|
||||||
void UpdateActiveZoneSet(_In_opt_ IZoneSet* zoneSet) noexcept;
|
void UpdateActiveZoneSet(_In_opt_ IZoneSet* zoneSet) noexcept;
|
||||||
LRESULT WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept;
|
LRESULT WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept;
|
||||||
void OnKeyUp(WPARAM wparam) noexcept;
|
|
||||||
std::vector<size_t> ZonesFromPoint(POINT pt) noexcept;
|
std::vector<size_t> ZonesFromPoint(POINT pt) noexcept;
|
||||||
void CycleActiveZoneSetInternal(DWORD wparam, Trace::ZoneWindow::InputMode mode) noexcept;
|
void SetAsTopmostWindow() noexcept;
|
||||||
|
|
||||||
winrt::com_ptr<IZoneWindowHost> m_host;
|
winrt::com_ptr<IZoneWindowHost> m_host;
|
||||||
HMONITOR m_monitor{};
|
HMONITOR m_monitor{};
|
||||||
@ -165,7 +164,7 @@ private:
|
|||||||
WPARAM m_keyLast{};
|
WPARAM m_keyLast{};
|
||||||
size_t m_keyCycle{};
|
size_t m_keyCycle{};
|
||||||
static const UINT m_showAnimationDuration = 200; // ms
|
static const UINT m_showAnimationDuration = 200; // ms
|
||||||
static const UINT m_flashDuration = 700; // ms
|
static const UINT m_flashDuration = 1000; // ms
|
||||||
std::unique_ptr<ZoneWindowDrawing> m_zoneWindowDrawing;
|
std::unique_ptr<ZoneWindowDrawing> m_zoneWindowDrawing;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -359,17 +358,6 @@ ZoneWindow::ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode) noexce
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IFACEMETHODIMP_(void)
|
|
||||||
ZoneWindow::CycleActiveZoneSet(DWORD wparam) noexcept
|
|
||||||
{
|
|
||||||
CycleActiveZoneSetInternal(wparam, Trace::ZoneWindow::InputMode::Keyboard);
|
|
||||||
|
|
||||||
if (m_windowMoveSize)
|
|
||||||
{
|
|
||||||
InvalidateRect(m_window, nullptr, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IFACEMETHODIMP_(void)
|
IFACEMETHODIMP_(void)
|
||||||
ZoneWindow::SaveWindowProcessToZoneIndex(HWND window) noexcept
|
ZoneWindow::SaveWindowProcessToZoneIndex(HWND window) noexcept
|
||||||
{
|
{
|
||||||
@ -392,23 +380,12 @@ ZoneWindow::SaveWindowProcessToZoneIndex(HWND window) noexcept
|
|||||||
IFACEMETHODIMP_(void)
|
IFACEMETHODIMP_(void)
|
||||||
ZoneWindow::ShowZoneWindow() noexcept
|
ZoneWindow::ShowZoneWindow() noexcept
|
||||||
{
|
{
|
||||||
auto window = m_window;
|
if (m_window)
|
||||||
if (!window)
|
|
||||||
{
|
{
|
||||||
return;
|
SetAsTopmostWindow();
|
||||||
|
m_zoneWindowDrawing->DrawActiveZoneSet(m_activeZoneSet->GetZones(), m_highlightZone, m_host);
|
||||||
|
m_zoneWindowDrawing->Show(m_showAnimationDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE;
|
|
||||||
|
|
||||||
HWND windowInsertAfter = m_windowMoveSize;
|
|
||||||
if (windowInsertAfter == nullptr)
|
|
||||||
{
|
|
||||||
windowInsertAfter = HWND_TOPMOST;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetWindowPos(window, windowInsertAfter, 0, 0, 0, 0, flags);
|
|
||||||
m_zoneWindowDrawing->Show(m_showAnimationDuration);
|
|
||||||
m_zoneWindowDrawing->DrawActiveZoneSet(m_activeZoneSet->GetZones(), m_highlightZone, m_host);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IFACEMETHODIMP_(void)
|
IFACEMETHODIMP_(void)
|
||||||
@ -427,6 +404,10 @@ IFACEMETHODIMP_(void)
|
|||||||
ZoneWindow::UpdateActiveZoneSet() noexcept
|
ZoneWindow::UpdateActiveZoneSet() noexcept
|
||||||
{
|
{
|
||||||
CalculateZoneSet();
|
CalculateZoneSet();
|
||||||
|
if (m_window)
|
||||||
|
{
|
||||||
|
m_zoneWindowDrawing->DrawActiveZoneSet(m_activeZoneSet->GetZones(), m_highlightZone, m_host);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IFACEMETHODIMP_(void)
|
IFACEMETHODIMP_(void)
|
||||||
@ -439,6 +420,17 @@ ZoneWindow::ClearSelectedZones() noexcept
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IFACEMETHODIMP_(void)
|
||||||
|
ZoneWindow::FlashZones() noexcept
|
||||||
|
{
|
||||||
|
if (m_window)
|
||||||
|
{
|
||||||
|
SetAsTopmostWindow();
|
||||||
|
m_zoneWindowDrawing->DrawActiveZoneSet(m_activeZoneSet->GetZones(), {}, m_host);
|
||||||
|
m_zoneWindowDrawing->Flash(m_flashDuration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#pragma region private
|
#pragma region private
|
||||||
|
|
||||||
void ZoneWindow::InitializeZoneSets(const std::wstring& parentUniqueId) noexcept
|
void ZoneWindow::InitializeZoneSets(const std::wstring& parentUniqueId) noexcept
|
||||||
@ -541,12 +533,6 @@ LRESULT ZoneWindow::WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept
|
|||||||
case WM_ERASEBKGND:
|
case WM_ERASEBKGND:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case WM_PAINT:
|
|
||||||
{
|
|
||||||
m_zoneWindowDrawing->ForceRender();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return DefWindowProc(m_window, message, wparam, lparam);
|
return DefWindowProc(m_window, message, wparam, lparam);
|
||||||
@ -555,18 +541,6 @@ LRESULT ZoneWindow::WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneWindow::OnKeyUp(WPARAM wparam) noexcept
|
|
||||||
{
|
|
||||||
bool fRedraw = false;
|
|
||||||
Trace::ZoneWindow::KeyUp(wparam);
|
|
||||||
|
|
||||||
if ((wparam >= '0') && (wparam <= '9'))
|
|
||||||
{
|
|
||||||
CycleActiveZoneSetInternal(static_cast<DWORD>(wparam), Trace::ZoneWindow::InputMode::Keyboard);
|
|
||||||
m_zoneWindowDrawing->DrawActiveZoneSet(m_activeZoneSet->GetZones(), m_highlightZone, m_host);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<size_t> ZoneWindow::ZonesFromPoint(POINT pt) noexcept
|
std::vector<size_t> ZoneWindow::ZonesFromPoint(POINT pt) noexcept
|
||||||
{
|
{
|
||||||
if (m_activeZoneSet)
|
if (m_activeZoneSet)
|
||||||
@ -576,52 +550,22 @@ std::vector<size_t> ZoneWindow::ZonesFromPoint(POINT pt) noexcept
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneWindow::CycleActiveZoneSetInternal(DWORD wparam, Trace::ZoneWindow::InputMode mode) noexcept
|
void ZoneWindow::SetAsTopmostWindow() noexcept
|
||||||
{
|
{
|
||||||
Trace::ZoneWindow::CycleActiveZoneSet(m_activeZoneSet, mode);
|
if (!m_window)
|
||||||
if (m_keyLast != wparam)
|
|
||||||
{
|
{
|
||||||
m_keyCycle = 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_keyLast = wparam;
|
UINT flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE;
|
||||||
|
|
||||||
bool loopAround = true;
|
HWND windowInsertAfter = m_windowMoveSize;
|
||||||
size_t const val = static_cast<size_t>(wparam - L'0');
|
if (windowInsertAfter == nullptr)
|
||||||
size_t i = 0;
|
|
||||||
for (auto zoneSet : m_zoneSets)
|
|
||||||
{
|
{
|
||||||
if (zoneSet->GetZones().size() == val)
|
windowInsertAfter = HWND_TOPMOST;
|
||||||
{
|
|
||||||
if (i < m_keyCycle)
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UpdateActiveZoneSet(zoneSet.get());
|
|
||||||
loopAround = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_keyCycle > 0) && loopAround)
|
SetWindowPos(m_window, windowInsertAfter, 0, 0, 0, 0, flags);
|
||||||
{
|
|
||||||
// Cycling through a non-empty group and hit the end
|
|
||||||
m_keyCycle = 0;
|
|
||||||
OnKeyUp(wparam);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_keyCycle++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_host)
|
|
||||||
{
|
|
||||||
m_host->MoveWindowsOnActiveZoneSetChange();
|
|
||||||
}
|
|
||||||
m_highlightZone = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
@ -86,13 +86,6 @@ interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IZoneWindow
|
|||||||
* zones available in the given direction.
|
* zones available in the given direction.
|
||||||
*/
|
*/
|
||||||
IFACEMETHOD_(bool, ExtendWindowByDirectionAndPosition)(HWND window, DWORD vkCode) = 0;
|
IFACEMETHOD_(bool, ExtendWindowByDirectionAndPosition)(HWND window, DWORD vkCode) = 0;
|
||||||
/**
|
|
||||||
* Cycle through active zone layouts (giving hints about each layout).
|
|
||||||
*
|
|
||||||
* @param vkCode Pressed key representing layout index.
|
|
||||||
*/
|
|
||||||
IFACEMETHOD_(void, CycleActiveZoneSet)(DWORD vkCode) = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save information about zone in which window was assigned, when closing the window.
|
* Save information about zone in which window was assigned, when closing the window.
|
||||||
* Used once we open same window again to assign it to its previous zone.
|
* Used once we open same window again to assign it to its previous zone.
|
||||||
@ -118,6 +111,10 @@ interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IZoneWindow
|
|||||||
* Clear the selected zones when this ZoneWindow loses focus.
|
* Clear the selected zones when this ZoneWindow loses focus.
|
||||||
*/
|
*/
|
||||||
IFACEMETHOD_(void, ClearSelectedZones)() = 0;
|
IFACEMETHOD_(void, ClearSelectedZones)() = 0;
|
||||||
|
/*
|
||||||
|
* Display the layout on the screen and then hide it.
|
||||||
|
*/
|
||||||
|
IFACEMETHOD_(void, FlashZones)() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
winrt::com_ptr<IZoneWindow> MakeZoneWindow(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monitor,
|
winrt::com_ptr<IZoneWindow> MakeZoneWindow(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monitor,
|
||||||
|
@ -19,18 +19,21 @@ float ZoneWindowDrawing::GetAnimationAlpha()
|
|||||||
// Lock is being held
|
// Lock is being held
|
||||||
if (!m_animation)
|
if (!m_animation)
|
||||||
{
|
{
|
||||||
return 1.f;
|
return 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tNow = std::chrono::steady_clock().now();
|
auto tNow = std::chrono::steady_clock().now();
|
||||||
auto alpha = (tNow - m_animation->tStart).count() / (1e6f * m_animation->duration);
|
auto alpha = (tNow - m_animation->tStart).count() / (1e6f * m_animation->duration);
|
||||||
if (alpha < 1.f)
|
|
||||||
|
if (m_animation->fadeIn)
|
||||||
{
|
{
|
||||||
return alpha;
|
// Return a positive value to avoid hiding
|
||||||
|
return std::clamp(alpha, 0.001f, 1.f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return 1.f;
|
// Quadratic function looks better
|
||||||
|
return std::clamp(1.f - alpha * alpha, 0.f, 1.f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,28 +103,7 @@ ZoneWindowDrawing::ZoneWindowDrawing(HWND window)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_renderThread = std::thread([this]() {
|
m_renderThread = std::thread([this]() { RenderLoop(); });
|
||||||
while (!m_abortThread)
|
|
||||||
{
|
|
||||||
// Force repeated rendering while in the animation loop.
|
|
||||||
// Yield if low latency locking was requested
|
|
||||||
if (!m_lowLatencyLock)
|
|
||||||
{
|
|
||||||
float animationAlpha;
|
|
||||||
{
|
|
||||||
std::unique_lock lock(m_mutex);
|
|
||||||
animationAlpha = GetAnimationAlpha();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (animationAlpha < 1.f)
|
|
||||||
{
|
|
||||||
m_shouldRender = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Render();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneWindowDrawing::Render()
|
void ZoneWindowDrawing::Render()
|
||||||
@ -133,11 +115,14 @@ void ZoneWindowDrawing::Render()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cv.wait(lock, [this]() { return (bool)m_shouldRender; });
|
float animationAlpha = GetAnimationAlpha();
|
||||||
|
|
||||||
|
if (animationAlpha <= 0.f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_renderTarget->BeginDraw();
|
m_renderTarget->BeginDraw();
|
||||||
|
|
||||||
float animationAlpha = GetAnimationAlpha();
|
|
||||||
|
|
||||||
// Draw backdrop
|
// Draw backdrop
|
||||||
m_renderTarget->Clear(D2D1::ColorF(0.f, 0.f, 0.f, 0.f));
|
m_renderTarget->Clear(D2D1::ColorF(0.f, 0.f, 0.f, 0.f));
|
||||||
@ -197,20 +182,49 @@ void ZoneWindowDrawing::Render()
|
|||||||
textBrush->Release();
|
textBrush->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The lock must be released here, as EndDraw() will wait for vertical sync
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
m_renderTarget->EndDraw();
|
m_renderTarget->EndDraw();
|
||||||
m_shouldRender = false;
|
}
|
||||||
|
|
||||||
|
void ZoneWindowDrawing::RenderLoop()
|
||||||
|
{
|
||||||
|
while (!m_abortThread)
|
||||||
|
{
|
||||||
|
float animationAlpha;
|
||||||
|
{
|
||||||
|
// The lock must be held by the caller when calling GetAnimationAlpha
|
||||||
|
std::unique_lock lock(m_mutex);
|
||||||
|
animationAlpha = GetAnimationAlpha();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether the animation expired and we need to hide the window
|
||||||
|
if (animationAlpha <= 0.f)
|
||||||
|
{
|
||||||
|
Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Wait here while rendering is disabled
|
||||||
|
std::unique_lock lock(m_mutex);
|
||||||
|
m_cv.wait(lock, [this]() { return (bool)m_shouldRender; });
|
||||||
|
}
|
||||||
|
|
||||||
|
Render();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneWindowDrawing::Hide()
|
void ZoneWindowDrawing::Hide()
|
||||||
{
|
{
|
||||||
_TRACER_;
|
_TRACER_;
|
||||||
m_lowLatencyLock = true;
|
|
||||||
std::unique_lock lock(m_mutex);
|
std::unique_lock lock(m_mutex);
|
||||||
m_lowLatencyLock = false;
|
|
||||||
|
|
||||||
if (m_animation)
|
m_animation.reset();
|
||||||
|
|
||||||
|
if (m_shouldRender)
|
||||||
{
|
{
|
||||||
m_animation.reset();
|
m_shouldRender = false;
|
||||||
ShowWindow(m_window, SW_HIDE);
|
ShowWindow(m_window, SW_HIDE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,20 +232,40 @@ void ZoneWindowDrawing::Hide()
|
|||||||
void ZoneWindowDrawing::Show(unsigned animationMillis)
|
void ZoneWindowDrawing::Show(unsigned animationMillis)
|
||||||
{
|
{
|
||||||
_TRACER_;
|
_TRACER_;
|
||||||
m_lowLatencyLock = true;
|
|
||||||
std::unique_lock lock(m_mutex);
|
std::unique_lock lock(m_mutex);
|
||||||
m_lowLatencyLock = false;
|
|
||||||
|
if (!m_shouldRender)
|
||||||
if (!m_animation)
|
|
||||||
{
|
{
|
||||||
ShowWindow(m_window, SW_SHOWNA);
|
ShowWindow(m_window, SW_SHOWNA);
|
||||||
if (animationMillis > 0)
|
|
||||||
{
|
|
||||||
m_animation.emplace(AnimationInfo{ std::chrono::steady_clock().now(), animationMillis });
|
|
||||||
}
|
|
||||||
m_shouldRender = true;
|
|
||||||
m_cv.notify_all();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
animationMillis = max(animationMillis, 1);
|
||||||
|
|
||||||
|
if (!m_animation || !m_animation->fadeIn)
|
||||||
|
{
|
||||||
|
m_animation.emplace(AnimationInfo{ std::chrono::steady_clock().now(), animationMillis, true });
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shouldRender = true;
|
||||||
|
m_cv.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZoneWindowDrawing::Flash(unsigned animationMillis)
|
||||||
|
{
|
||||||
|
_TRACER_;
|
||||||
|
std::unique_lock lock(m_mutex);
|
||||||
|
|
||||||
|
if (!m_shouldRender)
|
||||||
|
{
|
||||||
|
ShowWindow(m_window, SW_SHOWNA);
|
||||||
|
}
|
||||||
|
|
||||||
|
animationMillis = max(animationMillis, 1);
|
||||||
|
|
||||||
|
m_animation.emplace(AnimationInfo{ std::chrono::steady_clock().now(), animationMillis, false });
|
||||||
|
|
||||||
|
m_shouldRender = true;
|
||||||
|
m_cv.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneWindowDrawing::DrawActiveZoneSet(const IZoneSet::ZonesMap& zones,
|
void ZoneWindowDrawing::DrawActiveZoneSet(const IZoneSet::ZonesMap& zones,
|
||||||
@ -239,9 +273,7 @@ void ZoneWindowDrawing::DrawActiveZoneSet(const IZoneSet::ZonesMap& zones,
|
|||||||
winrt::com_ptr<IZoneWindowHost> host)
|
winrt::com_ptr<IZoneWindowHost> host)
|
||||||
{
|
{
|
||||||
_TRACER_;
|
_TRACER_;
|
||||||
m_lowLatencyLock = true;
|
|
||||||
std::unique_lock lock(m_mutex);
|
std::unique_lock lock(m_mutex);
|
||||||
m_lowLatencyLock = false;
|
|
||||||
|
|
||||||
m_sceneRects = {};
|
m_sceneRects = {};
|
||||||
|
|
||||||
@ -299,18 +331,6 @@ void ZoneWindowDrawing::DrawActiveZoneSet(const IZoneSet::ZonesMap& zones,
|
|||||||
m_sceneRects.push_back(drawableRect);
|
m_sceneRects.push_back(drawableRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_shouldRender = true;
|
|
||||||
m_cv.notify_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZoneWindowDrawing::ForceRender()
|
|
||||||
{
|
|
||||||
m_lowLatencyLock = true;
|
|
||||||
std::unique_lock lock(m_mutex);
|
|
||||||
m_lowLatencyLock = false;
|
|
||||||
m_shouldRender = true;
|
|
||||||
m_cv.notify_all();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ZoneWindowDrawing::~ZoneWindowDrawing()
|
ZoneWindowDrawing::~ZoneWindowDrawing()
|
||||||
|
@ -26,6 +26,7 @@ class ZoneWindowDrawing
|
|||||||
{
|
{
|
||||||
std::chrono::steady_clock::time_point tStart;
|
std::chrono::steady_clock::time_point tStart;
|
||||||
unsigned duration;
|
unsigned duration;
|
||||||
|
bool fadeIn;
|
||||||
};
|
};
|
||||||
|
|
||||||
HWND m_window = nullptr;
|
HWND m_window = nullptr;
|
||||||
@ -42,10 +43,10 @@ class ZoneWindowDrawing
|
|||||||
static D2D1_COLOR_F ConvertColor(COLORREF color);
|
static D2D1_COLOR_F ConvertColor(COLORREF color);
|
||||||
static D2D1_RECT_F ConvertRect(RECT rect);
|
static D2D1_RECT_F ConvertRect(RECT rect);
|
||||||
void Render();
|
void Render();
|
||||||
|
void RenderLoop();
|
||||||
|
|
||||||
std::atomic<bool> m_shouldRender = false;
|
std::atomic<bool> m_shouldRender = false;
|
||||||
std::atomic<bool> m_abortThread = false;
|
std::atomic<bool> m_abortThread = false;
|
||||||
std::atomic<bool> m_lowLatencyLock = false;
|
|
||||||
std::condition_variable m_cv;
|
std::condition_variable m_cv;
|
||||||
std::thread m_renderThread;
|
std::thread m_renderThread;
|
||||||
|
|
||||||
@ -55,7 +56,7 @@ public:
|
|||||||
ZoneWindowDrawing(HWND window);
|
ZoneWindowDrawing(HWND window);
|
||||||
void Hide();
|
void Hide();
|
||||||
void Show(unsigned animationMillis);
|
void Show(unsigned animationMillis);
|
||||||
void ForceRender();
|
void Flash(unsigned animationMillis);
|
||||||
void DrawActiveZoneSet(const IZoneSet::ZonesMap& zones,
|
void DrawActiveZoneSet(const IZoneSet::ZonesMap& zones,
|
||||||
const std::vector<size_t>& highlightZones,
|
const std::vector<size_t>& highlightZones,
|
||||||
winrt::com_ptr<IZoneWindowHost> host);
|
winrt::com_ptr<IZoneWindowHost> host);
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#define EventZoneWindowKeyUpKey "FancyZones_ZoneWindowKeyUp"
|
#define EventZoneWindowKeyUpKey "FancyZones_ZoneWindowKeyUp"
|
||||||
#define EventMoveSizeEndKey "FancyZones_MoveSizeEnd"
|
#define EventMoveSizeEndKey "FancyZones_MoveSizeEnd"
|
||||||
#define EventCycleActiveZoneSetKey "FancyZones_CycleActiveZoneSet"
|
#define EventCycleActiveZoneSetKey "FancyZones_CycleActiveZoneSet"
|
||||||
|
#define EventQuickLayoutSwitchKey "FancyZones_QuickLayoutSwitch"
|
||||||
|
|
||||||
#define EventEnabledKey "Enabled"
|
#define EventEnabledKey "Enabled"
|
||||||
#define PressedKeyCodeKey "Hotkey"
|
#define PressedKeyCodeKey "Hotkey"
|
||||||
@ -25,6 +26,7 @@
|
|||||||
#define MoveSizeActionKey "InMoveSize"
|
#define MoveSizeActionKey "InMoveSize"
|
||||||
#define AppsInHistoryCountKey "AppsInHistoryCount"
|
#define AppsInHistoryCountKey "AppsInHistoryCount"
|
||||||
#define CustomZoneSetCountKey "CustomZoneSetCount"
|
#define CustomZoneSetCountKey "CustomZoneSetCount"
|
||||||
|
#define LayoutUsingQuickKeyCountKey "LayoutUsingQuickKeyCount"
|
||||||
#define NumberOfZonesForEachCustomZoneSetKey "NumberOfZonesForEachCustomZoneSet"
|
#define NumberOfZonesForEachCustomZoneSetKey "NumberOfZonesForEachCustomZoneSet"
|
||||||
#define ActiveZoneSetsCountKey "ActiveZoneSetsCount"
|
#define ActiveZoneSetsCountKey "ActiveZoneSetsCount"
|
||||||
#define ActiveZoneSetsListKey "ActiveZoneSetsList"
|
#define ActiveZoneSetsListKey "ActiveZoneSetsList"
|
||||||
@ -40,6 +42,8 @@
|
|||||||
#define MoveWindowsToLastZoneOnAppOpeningKey "MoveWindowsToLastZoneOnAppOpening"
|
#define MoveWindowsToLastZoneOnAppOpeningKey "MoveWindowsToLastZoneOnAppOpening"
|
||||||
#define OpenWindowOnActiveMonitorKey "OpenWindowOnActiveMonitor"
|
#define OpenWindowOnActiveMonitorKey "OpenWindowOnActiveMonitor"
|
||||||
#define RestoreSizeKey "RestoreSize"
|
#define RestoreSizeKey "RestoreSize"
|
||||||
|
#define QuickLayoutSwitchKey "QuickLayoutSwitch"
|
||||||
|
#define FlashZonesOnQuickSwitchKey "FlashZonesOnQuickSwitch"
|
||||||
#define UseCursorPosOnEditorStartupKey "UseCursorPosOnEditorStartup"
|
#define UseCursorPosOnEditorStartupKey "UseCursorPosOnEditorStartup"
|
||||||
#define ShowZonesOnAllMonitorsKey "ShowZonesOnAllMonitors"
|
#define ShowZonesOnAllMonitorsKey "ShowZonesOnAllMonitors"
|
||||||
#define SpanZonesAcrossMonitorsKey "SpanZonesAcrossMonitors"
|
#define SpanZonesAcrossMonitorsKey "SpanZonesAcrossMonitors"
|
||||||
@ -56,6 +60,7 @@
|
|||||||
#define NumberOfWindowsKey "NumberOfWindows"
|
#define NumberOfWindowsKey "NumberOfWindows"
|
||||||
#define InputModeKey "InputMode"
|
#define InputModeKey "InputMode"
|
||||||
#define OverlappingZonesAlgorithmKey "OverlappingZonesAlgorithm"
|
#define OverlappingZonesAlgorithmKey "OverlappingZonesAlgorithm"
|
||||||
|
#define QuickLayoutSwitchedWithShortcutUsed "ShortcutUsed"
|
||||||
|
|
||||||
TRACELOGGING_DEFINE_PROVIDER(
|
TRACELOGGING_DEFINE_PROVIDER(
|
||||||
g_hProvider,
|
g_hProvider,
|
||||||
@ -128,6 +133,7 @@ void Trace::FancyZones::DataChanged() noexcept
|
|||||||
int appsHistorySize = static_cast<int>(data.GetAppZoneHistoryMap().size());
|
int appsHistorySize = static_cast<int>(data.GetAppZoneHistoryMap().size());
|
||||||
const auto& customZones = data.GetCustomZoneSetsMap();
|
const auto& customZones = data.GetCustomZoneSetsMap();
|
||||||
const auto& devices = data.GetDeviceInfoMap();
|
const auto& devices = data.GetDeviceInfoMap();
|
||||||
|
const auto& quickKeys = data.GetLayoutQuickKeys();
|
||||||
|
|
||||||
std::unique_ptr<INT32[]> customZonesArray(new (std::nothrow) INT32[customZones.size()]);
|
std::unique_ptr<INT32[]> customZonesArray(new (std::nothrow) INT32[customZones.size()]);
|
||||||
if (!customZonesArray)
|
if (!customZonesArray)
|
||||||
@ -149,7 +155,7 @@ void Trace::FancyZones::DataChanged() noexcept
|
|||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
//NumberOfZonesForEachCustomZoneSet
|
// NumberOfZonesForEachCustomZoneSet
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const auto& [id, customZoneSetData] : customZones)
|
for (const auto& [id, customZoneSetData] : customZones)
|
||||||
{
|
{
|
||||||
@ -157,7 +163,7 @@ void Trace::FancyZones::DataChanged() noexcept
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//ActiveZoneSetsList
|
// ActiveZoneSetsList
|
||||||
std::wstring activeZoneSetInfo;
|
std::wstring activeZoneSetInfo;
|
||||||
for (const auto& [id, device] : devices)
|
for (const auto& [id, device] : devices)
|
||||||
{
|
{
|
||||||
@ -201,7 +207,8 @@ void Trace::FancyZones::DataChanged() noexcept
|
|||||||
TraceLoggingInt32(static_cast<int>(customZones.size()), CustomZoneSetCountKey),
|
TraceLoggingInt32(static_cast<int>(customZones.size()), CustomZoneSetCountKey),
|
||||||
TraceLoggingInt32Array(customZonesArray.get(), static_cast<int>(customZones.size()), NumberOfZonesForEachCustomZoneSetKey),
|
TraceLoggingInt32Array(customZonesArray.get(), static_cast<int>(customZones.size()), NumberOfZonesForEachCustomZoneSetKey),
|
||||||
TraceLoggingInt32(static_cast<int>(devices.size()), ActiveZoneSetsCountKey),
|
TraceLoggingInt32(static_cast<int>(devices.size()), ActiveZoneSetsCountKey),
|
||||||
TraceLoggingWideString(activeZoneSetInfo.c_str(), ActiveZoneSetsListKey));
|
TraceLoggingWideString(activeZoneSetInfo.c_str(), ActiveZoneSetsListKey),
|
||||||
|
TraceLoggingInt32(static_cast<int>(quickKeys.size()), LayoutUsingQuickKeyCountKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Trace::FancyZones::EditorLaunched(int value) noexcept
|
void Trace::FancyZones::EditorLaunched(int value) noexcept
|
||||||
@ -227,6 +234,16 @@ void Trace::FancyZones::Error(const DWORD errorCode, std::wstring errorMessage,
|
|||||||
TraceLoggingValue(errorMessage.c_str(), "ErrorMessage"));
|
TraceLoggingValue(errorMessage.c_str(), "ErrorMessage"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Trace::FancyZones::QuickLayoutSwitched(bool shortcutUsed) noexcept
|
||||||
|
{
|
||||||
|
TraceLoggingWrite(
|
||||||
|
g_hProvider,
|
||||||
|
EventQuickLayoutSwitchKey,
|
||||||
|
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||||
|
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
|
||||||
|
TraceLoggingBoolean(shortcutUsed, QuickLayoutSwitchedWithShortcutUsed));
|
||||||
|
}
|
||||||
|
|
||||||
void Trace::SettingsChanged(const Settings& settings) noexcept
|
void Trace::SettingsChanged(const Settings& settings) noexcept
|
||||||
{
|
{
|
||||||
const auto& editorHotkey = settings.editorHotkey;
|
const auto& editorHotkey = settings.editorHotkey;
|
||||||
@ -253,6 +270,8 @@ void Trace::SettingsChanged(const Settings& settings) noexcept
|
|||||||
TraceLoggingBoolean(settings.appLastZone_moveWindows, MoveWindowsToLastZoneOnAppOpeningKey),
|
TraceLoggingBoolean(settings.appLastZone_moveWindows, MoveWindowsToLastZoneOnAppOpeningKey),
|
||||||
TraceLoggingBoolean(settings.openWindowOnActiveMonitor, OpenWindowOnActiveMonitorKey),
|
TraceLoggingBoolean(settings.openWindowOnActiveMonitor, OpenWindowOnActiveMonitorKey),
|
||||||
TraceLoggingBoolean(settings.restoreSize, RestoreSizeKey),
|
TraceLoggingBoolean(settings.restoreSize, RestoreSizeKey),
|
||||||
|
TraceLoggingBoolean(settings.quickLayoutSwitch, QuickLayoutSwitchKey),
|
||||||
|
TraceLoggingBoolean(settings.flashZonesOnQuickSwitch, FlashZonesOnQuickSwitchKey),
|
||||||
TraceLoggingBoolean(settings.use_cursorpos_editor_startupscreen, UseCursorPosOnEditorStartupKey),
|
TraceLoggingBoolean(settings.use_cursorpos_editor_startupscreen, UseCursorPosOnEditorStartupKey),
|
||||||
TraceLoggingBoolean(settings.showZonesOnAllMonitors, ShowZonesOnAllMonitorsKey),
|
TraceLoggingBoolean(settings.showZonesOnAllMonitors, ShowZonesOnAllMonitorsKey),
|
||||||
TraceLoggingBoolean(settings.spanZonesAcrossMonitors, SpanZonesAcrossMonitorsKey),
|
TraceLoggingBoolean(settings.spanZonesAcrossMonitors, SpanZonesAcrossMonitorsKey),
|
||||||
|
@ -17,6 +17,7 @@ public:
|
|||||||
static void DataChanged() noexcept;
|
static void DataChanged() noexcept;
|
||||||
static void EditorLaunched(int value) noexcept;
|
static void EditorLaunched(int value) noexcept;
|
||||||
static void Error(const DWORD errorCode, std::wstring errorMessage, std::wstring methodName) noexcept;
|
static void Error(const DWORD errorCode, std::wstring errorMessage, std::wstring methodName) noexcept;
|
||||||
|
static void QuickLayoutSwitched(bool shortcutUsed) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void SettingsChanged(const Settings& settings) noexcept;
|
static void SettingsChanged(const Settings& settings) noexcept;
|
||||||
|
@ -78,6 +78,8 @@ namespace FancyZonesUnitTests
|
|||||||
ptSettings.add_bool_toggle(L"fancyzones_zoneSetChange_moveWindows", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS, settings.zoneSetChange_moveWindows);
|
ptSettings.add_bool_toggle(L"fancyzones_zoneSetChange_moveWindows", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS, settings.zoneSetChange_moveWindows);
|
||||||
ptSettings.add_bool_toggle(L"fancyzones_appLastZone_moveWindows", IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS, settings.appLastZone_moveWindows);
|
ptSettings.add_bool_toggle(L"fancyzones_appLastZone_moveWindows", IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS, settings.appLastZone_moveWindows);
|
||||||
ptSettings.add_bool_toggle(L"fancyzones_restoreSize", IDS_SETTING_DESCRIPTION_RESTORESIZE, settings.restoreSize);
|
ptSettings.add_bool_toggle(L"fancyzones_restoreSize", IDS_SETTING_DESCRIPTION_RESTORESIZE, settings.restoreSize);
|
||||||
|
ptSettings.add_bool_toggle(L"fancyzones_quickLayoutSwitch", IDS_SETTING_DESCRIPTION_QUICKLAYOUTSWITCH, settings.quickLayoutSwitch);
|
||||||
|
ptSettings.add_bool_toggle(L"fancyzones_flashZonesOnQuickSwitch", IDS_SETTING_DESCRIPTION_FLASHZONESONQUICKSWITCH, settings.flashZonesOnQuickSwitch);
|
||||||
ptSettings.add_bool_toggle(L"use_cursorpos_editor_startupscreen", IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN, settings.use_cursorpos_editor_startupscreen);
|
ptSettings.add_bool_toggle(L"use_cursorpos_editor_startupscreen", IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN, settings.use_cursorpos_editor_startupscreen);
|
||||||
ptSettings.add_bool_toggle(L"fancyzones_show_on_all_monitors", IDS_SETTING_DESCRIPTION_SHOW_FANCY_ZONES_ON_ALL_MONITORS, settings.showZonesOnAllMonitors);
|
ptSettings.add_bool_toggle(L"fancyzones_show_on_all_monitors", IDS_SETTING_DESCRIPTION_SHOW_FANCY_ZONES_ON_ALL_MONITORS, settings.showZonesOnAllMonitors);
|
||||||
ptSettings.add_bool_toggle(L"fancyzones_multi_monitor_mode", IDS_SETTING_DESCRIPTION_SPAN_ZONES_ACROSS_MONITORS, settings.spanZonesAcrossMonitors);
|
ptSettings.add_bool_toggle(L"fancyzones_multi_monitor_mode", IDS_SETTING_DESCRIPTION_SPAN_ZONES_ACROSS_MONITORS, settings.spanZonesAcrossMonitors);
|
||||||
@ -303,6 +305,8 @@ namespace FancyZonesUnitTests
|
|||||||
ptSettings.add_bool_toggle(L"fancyzones_zoneSetChange_moveWindows", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS, settings.zoneSetChange_moveWindows);
|
ptSettings.add_bool_toggle(L"fancyzones_zoneSetChange_moveWindows", IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS, settings.zoneSetChange_moveWindows);
|
||||||
ptSettings.add_bool_toggle(L"fancyzones_appLastZone_moveWindows", IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS, settings.appLastZone_moveWindows);
|
ptSettings.add_bool_toggle(L"fancyzones_appLastZone_moveWindows", IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS, settings.appLastZone_moveWindows);
|
||||||
ptSettings.add_bool_toggle(L"fancyzones_restoreSize", IDS_SETTING_DESCRIPTION_RESTORESIZE, settings.restoreSize);
|
ptSettings.add_bool_toggle(L"fancyzones_restoreSize", IDS_SETTING_DESCRIPTION_RESTORESIZE, settings.restoreSize);
|
||||||
|
ptSettings.add_bool_toggle(L"fancyzones_quickLayoutSwitch", IDS_SETTING_DESCRIPTION_QUICKLAYOUTSWITCH, settings.quickLayoutSwitch);
|
||||||
|
ptSettings.add_bool_toggle(L"fancyzones_flashZonesOnQuickSwitch", IDS_SETTING_DESCRIPTION_FLASHZONESONQUICKSWITCH, settings.flashZonesOnQuickSwitch);
|
||||||
ptSettings.add_bool_toggle(L"use_cursorpos_editor_startupscreen", IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN, settings.use_cursorpos_editor_startupscreen);
|
ptSettings.add_bool_toggle(L"use_cursorpos_editor_startupscreen", IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN, settings.use_cursorpos_editor_startupscreen);
|
||||||
ptSettings.add_bool_toggle(L"fancyzones_show_on_all_monitors", IDS_SETTING_DESCRIPTION_SHOW_FANCY_ZONES_ON_ALL_MONITORS, settings.showZonesOnAllMonitors);
|
ptSettings.add_bool_toggle(L"fancyzones_show_on_all_monitors", IDS_SETTING_DESCRIPTION_SHOW_FANCY_ZONES_ON_ALL_MONITORS, settings.showZonesOnAllMonitors);
|
||||||
ptSettings.add_bool_toggle(L"fancyzones_multi_monitor_mode", IDS_SETTING_DESCRIPTION_SPAN_ZONES_ACROSS_MONITORS, settings.spanZonesAcrossMonitors);
|
ptSettings.add_bool_toggle(L"fancyzones_multi_monitor_mode", IDS_SETTING_DESCRIPTION_SPAN_ZONES_ACROSS_MONITORS, settings.spanZonesAcrossMonitors);
|
||||||
|
@ -1539,6 +1539,73 @@ namespace FancyZonesUnitTests
|
|||||||
compareJsonArrays(expected, actual);
|
compareJsonArrays(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(QuickLayoutKeysParse)
|
||||||
|
{
|
||||||
|
const std::wstring zoneUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}";
|
||||||
|
LayoutQuickKeyJSON expected{ zoneUuid, 2 };
|
||||||
|
json::JsonArray array;
|
||||||
|
array.Append(LayoutQuickKeyJSON::ToJson(expected));
|
||||||
|
|
||||||
|
json::JsonObject json;
|
||||||
|
json.SetNamedValue(L"quick-layout-keys", json::JsonValue::Parse(array.Stringify()));
|
||||||
|
|
||||||
|
const auto& quickKeysMap = ParseQuickKeys(json);
|
||||||
|
|
||||||
|
Assert::AreEqual((size_t)array.Size(), quickKeysMap.size());
|
||||||
|
|
||||||
|
Assert::IsTrue(quickKeysMap.find(zoneUuid) != quickKeysMap.end());
|
||||||
|
int actualKey = quickKeysMap.find(zoneUuid)->second;
|
||||||
|
Assert::AreEqual((int)expected.key, actualKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (QuickLayoutKeysParseEmpty)
|
||||||
|
{
|
||||||
|
json::JsonArray array;
|
||||||
|
json::JsonObject json;
|
||||||
|
json.SetNamedValue(L"quick-layout-keys", json::JsonValue::Parse(array.Stringify()));
|
||||||
|
|
||||||
|
const auto& quickKeysMap = ParseQuickKeys(json);
|
||||||
|
|
||||||
|
Assert::IsTrue(quickKeysMap.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (QuickLayoutKeysParseInvalid)
|
||||||
|
{
|
||||||
|
const std::wstring invalidZoneUuid = L"{33A2B101-06E0-437B-}";
|
||||||
|
LayoutQuickKeyJSON expected{ invalidZoneUuid, 2 };
|
||||||
|
json::JsonArray array;
|
||||||
|
array.Append(LayoutQuickKeyJSON::ToJson(expected));
|
||||||
|
|
||||||
|
json::JsonObject json;
|
||||||
|
json.SetNamedValue(L"quick-layout-keys", json::JsonValue::Parse(array.Stringify()));
|
||||||
|
|
||||||
|
const auto& quickKeysMap = ParseQuickKeys(json);
|
||||||
|
|
||||||
|
Assert::IsTrue(quickKeysMap.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (QuickLayoutKeysParseMissed)
|
||||||
|
{
|
||||||
|
json::JsonObject json;
|
||||||
|
|
||||||
|
const auto& quickKeysMap = ParseQuickKeys(json);
|
||||||
|
|
||||||
|
Assert::IsTrue(quickKeysMap.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (QuickLayoutKeysSerialize)
|
||||||
|
{
|
||||||
|
json::JsonArray expected;
|
||||||
|
expected.Append(LayoutQuickKeyJSON::ToJson(LayoutQuickKeyJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", 3}));
|
||||||
|
json::JsonObject json;
|
||||||
|
json.SetNamedValue(L"quick-layout-keys", json::JsonValue::Parse(expected.Stringify()));
|
||||||
|
|
||||||
|
const auto& quickKeysMap = ParseQuickKeys(json);
|
||||||
|
|
||||||
|
auto actual = SerializeQuickKeys(quickKeysMap);
|
||||||
|
compareJsonArrays(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_METHOD (SetActiveZoneSet)
|
TEST_METHOD (SetActiveZoneSet)
|
||||||
{
|
{
|
||||||
FancyZonesData data;
|
FancyZonesData data;
|
||||||
@ -1640,14 +1707,17 @@ namespace FancyZonesUnitTests
|
|||||||
};
|
};
|
||||||
AppZoneHistoryJSON appZoneHistory{ L"app-path", std::vector<AppZoneHistoryData>{ data } };
|
AppZoneHistoryJSON appZoneHistory{ L"app-path", std::vector<AppZoneHistoryData>{ data } };
|
||||||
DeviceInfoJSON deviceInfo{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 } };
|
DeviceInfoJSON deviceInfo{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 } };
|
||||||
json::JsonArray zoneSetsArray, appZonesArray, deviceInfoArray;
|
LayoutQuickKeyJSON quickKeys{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", 1 };
|
||||||
|
json::JsonArray zoneSetsArray, appZonesArray, deviceInfoArray, quickKeysArray;
|
||||||
zoneSetsArray.Append(CustomZoneSetJSON::ToJson(zoneSets));
|
zoneSetsArray.Append(CustomZoneSetJSON::ToJson(zoneSets));
|
||||||
appZonesArray.Append(AppZoneHistoryJSON::ToJson(appZoneHistory));
|
appZonesArray.Append(AppZoneHistoryJSON::ToJson(appZoneHistory));
|
||||||
deviceInfoArray.Append(DeviceInfoJSON::ToJson(deviceInfo));
|
deviceInfoArray.Append(DeviceInfoJSON::ToJson(deviceInfo));
|
||||||
|
quickKeysArray.Append(LayoutQuickKeyJSON::ToJson(quickKeys));
|
||||||
json::JsonObject fancyZones;
|
json::JsonObject fancyZones;
|
||||||
fancyZones.SetNamedValue(L"custom-zone-sets", zoneSetsArray);
|
fancyZones.SetNamedValue(L"custom-zone-sets", zoneSetsArray);
|
||||||
fancyZones.SetNamedValue(L"app-zone-history", appZonesArray);
|
fancyZones.SetNamedValue(L"app-zone-history", appZonesArray);
|
||||||
fancyZones.SetNamedValue(L"devices", deviceInfoArray);
|
fancyZones.SetNamedValue(L"devices", deviceInfoArray);
|
||||||
|
fancyZones.SetNamedValue(L"quick-layout-keys", quickKeysArray);
|
||||||
|
|
||||||
json::to_file(jsonPath, fancyZones);
|
json::to_file(jsonPath, fancyZones);
|
||||||
|
|
||||||
@ -1664,6 +1734,7 @@ namespace FancyZonesUnitTests
|
|||||||
Assert::IsFalse(fancyZonesData.GetCustomZoneSetsMap().empty());
|
Assert::IsFalse(fancyZonesData.GetCustomZoneSetsMap().empty());
|
||||||
Assert::IsFalse(fancyZonesData.GetCustomZoneSetsMap().empty());
|
Assert::IsFalse(fancyZonesData.GetCustomZoneSetsMap().empty());
|
||||||
Assert::IsFalse(fancyZonesData.GetCustomZoneSetsMap().empty());
|
Assert::IsFalse(fancyZonesData.GetCustomZoneSetsMap().empty());
|
||||||
|
Assert::IsFalse(fancyZonesData.GetLayoutQuickKeys().empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD (LoadFancyZonesDataFromCroppedJson)
|
TEST_METHOD (LoadFancyZonesDataFromCroppedJson)
|
||||||
|
@ -14,5 +14,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
|||||||
// Fancy Zones Default Flags.
|
// Fancy Zones Default Flags.
|
||||||
public static readonly bool DefaultFancyzonesShiftDrag = true;
|
public static readonly bool DefaultFancyzonesShiftDrag = true;
|
||||||
public static readonly bool DefaultUseCursorposEditorStartupscreen = true;
|
public static readonly bool DefaultUseCursorposEditorStartupscreen = true;
|
||||||
|
public static readonly bool DefaultFancyzonesQuickLayoutSwitch = true;
|
||||||
|
public static readonly bool DefaultFancyzonesFlashZonesOnQuickSwitch = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
|||||||
FancyzonesAppLastZoneMoveWindows = new BoolProperty();
|
FancyzonesAppLastZoneMoveWindows = new BoolProperty();
|
||||||
FancyzonesOpenWindowOnActiveMonitor = new BoolProperty();
|
FancyzonesOpenWindowOnActiveMonitor = new BoolProperty();
|
||||||
FancyzonesRestoreSize = new BoolProperty();
|
FancyzonesRestoreSize = new BoolProperty();
|
||||||
|
FancyzonesQuickLayoutSwitch = new BoolProperty(ConfigDefaults.DefaultFancyzonesQuickLayoutSwitch);
|
||||||
|
FancyzonesFlashZonesOnQuickSwitch = new BoolProperty(ConfigDefaults.DefaultFancyzonesFlashZonesOnQuickSwitch);
|
||||||
UseCursorposEditorStartupscreen = new BoolProperty(ConfigDefaults.DefaultUseCursorposEditorStartupscreen);
|
UseCursorposEditorStartupscreen = new BoolProperty(ConfigDefaults.DefaultUseCursorposEditorStartupscreen);
|
||||||
FancyzonesShowOnAllMonitors = new BoolProperty();
|
FancyzonesShowOnAllMonitors = new BoolProperty();
|
||||||
FancyzonesSpanZonesAcrossMonitors = new BoolProperty();
|
FancyzonesSpanZonesAcrossMonitors = new BoolProperty();
|
||||||
@ -69,6 +71,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
|||||||
[JsonPropertyName("fancyzones_restoreSize")]
|
[JsonPropertyName("fancyzones_restoreSize")]
|
||||||
public BoolProperty FancyzonesRestoreSize { get; set; }
|
public BoolProperty FancyzonesRestoreSize { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("fancyzones_quickLayoutSwitch")]
|
||||||
|
public BoolProperty FancyzonesQuickLayoutSwitch { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("fancyzones_flashZonesOnQuickSwitch")]
|
||||||
|
public BoolProperty FancyzonesFlashZonesOnQuickSwitch { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("use_cursorpos_editor_startupscreen")]
|
[JsonPropertyName("use_cursorpos_editor_startupscreen")]
|
||||||
public BoolProperty UseCursorposEditorStartupscreen { get; set; }
|
public BoolProperty UseCursorposEditorStartupscreen { get; set; }
|
||||||
|
|
||||||
|
@ -71,6 +71,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
|||||||
_appLastZoneMoveWindows = Settings.Properties.FancyzonesAppLastZoneMoveWindows.Value;
|
_appLastZoneMoveWindows = Settings.Properties.FancyzonesAppLastZoneMoveWindows.Value;
|
||||||
_openWindowOnActiveMonitor = Settings.Properties.FancyzonesOpenWindowOnActiveMonitor.Value;
|
_openWindowOnActiveMonitor = Settings.Properties.FancyzonesOpenWindowOnActiveMonitor.Value;
|
||||||
_restoreSize = Settings.Properties.FancyzonesRestoreSize.Value;
|
_restoreSize = Settings.Properties.FancyzonesRestoreSize.Value;
|
||||||
|
_quickLayoutSwitch = Settings.Properties.FancyzonesQuickLayoutSwitch.Value;
|
||||||
|
_flashZonesOnQuickLayoutSwitch = Settings.Properties.FancyzonesFlashZonesOnQuickSwitch.Value;
|
||||||
_useCursorPosEditorStartupScreen = Settings.Properties.UseCursorposEditorStartupscreen.Value;
|
_useCursorPosEditorStartupScreen = Settings.Properties.UseCursorposEditorStartupscreen.Value;
|
||||||
_showOnAllMonitors = Settings.Properties.FancyzonesShowOnAllMonitors.Value;
|
_showOnAllMonitors = Settings.Properties.FancyzonesShowOnAllMonitors.Value;
|
||||||
_spanZonesAcrossMonitors = Settings.Properties.FancyzonesSpanZonesAcrossMonitors.Value;
|
_spanZonesAcrossMonitors = Settings.Properties.FancyzonesSpanZonesAcrossMonitors.Value;
|
||||||
@ -107,6 +109,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
|||||||
private bool _openWindowOnActiveMonitor;
|
private bool _openWindowOnActiveMonitor;
|
||||||
private bool _spanZonesAcrossMonitors;
|
private bool _spanZonesAcrossMonitors;
|
||||||
private bool _restoreSize;
|
private bool _restoreSize;
|
||||||
|
private bool _quickLayoutSwitch;
|
||||||
|
private bool _flashZonesOnQuickLayoutSwitch;
|
||||||
private bool _useCursorPosEditorStartupScreen;
|
private bool _useCursorPosEditorStartupScreen;
|
||||||
private bool _showOnAllMonitors;
|
private bool _showOnAllMonitors;
|
||||||
private bool _makeDraggedWindowTransparent;
|
private bool _makeDraggedWindowTransparent;
|
||||||
@ -138,6 +142,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
|||||||
SendConfigMSG(snd.ToString());
|
SendConfigMSG(snd.ToString());
|
||||||
OnPropertyChanged(nameof(IsEnabled));
|
OnPropertyChanged(nameof(IsEnabled));
|
||||||
OnPropertyChanged(nameof(SnapHotkeysCategoryEnabled));
|
OnPropertyChanged(nameof(SnapHotkeysCategoryEnabled));
|
||||||
|
OnPropertyChanged(nameof(QuickSwitchEnabled));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,6 +155,14 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool QuickSwitchEnabled
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _isEnabled && _quickLayoutSwitch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool ShiftDrag
|
public bool ShiftDrag
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -374,6 +387,43 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool QuickLayoutSwitch
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _quickLayoutSwitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _quickLayoutSwitch)
|
||||||
|
{
|
||||||
|
_quickLayoutSwitch = value;
|
||||||
|
Settings.Properties.FancyzonesQuickLayoutSwitch.Value = value;
|
||||||
|
NotifyPropertyChanged();
|
||||||
|
OnPropertyChanged(nameof(QuickSwitchEnabled));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool FlashZonesOnQuickSwitch
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _flashZonesOnQuickLayoutSwitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _flashZonesOnQuickLayoutSwitch)
|
||||||
|
{
|
||||||
|
_flashZonesOnQuickLayoutSwitch = value;
|
||||||
|
Settings.Properties.FancyzonesFlashZonesOnQuickSwitch.Value = value;
|
||||||
|
NotifyPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool UseCursorPosEditorStartupScreen
|
public bool UseCursorPosEditorStartupScreen
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -1176,4 +1176,13 @@ Win + Shift + O to toggle your video</value>
|
|||||||
<data name="ColorPicker_ButtonUp.AutomationProperties.Name" xml:space="preserve">
|
<data name="ColorPicker_ButtonUp.AutomationProperties.Name" xml:space="preserve">
|
||||||
<value>Move the color up</value>
|
<value>Move the color up</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="FancyZones_FlashZonesOnQuickSwitch.Content" xml:space="preserve">
|
||||||
|
<value>Flash zones when switching layout</value>
|
||||||
|
</data>
|
||||||
|
<data name="FancyZones_QuickLayoutSwitch.Content" xml:space="preserve">
|
||||||
|
<value>Enable quick layout switch</value>
|
||||||
|
</data>
|
||||||
|
<data name="FancyZones_QuickLayoutSwitch_GroupSettings.Text" xml:space="preserve">
|
||||||
|
<value>Quick layout switch</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -189,6 +189,20 @@
|
|||||||
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"/>
|
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"/>
|
||||||
|
|
||||||
|
|
||||||
|
<TextBlock x:Uid="FancyZones_QuickLayoutSwitch_GroupSettings"
|
||||||
|
Style="{StaticResource SettingsGroupTitleStyle}"
|
||||||
|
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled, Converter={StaticResource ModuleEnabledToForegroundConverter}}"/>
|
||||||
|
|
||||||
|
<CheckBox x:Uid="FancyZones_QuickLayoutSwitch"
|
||||||
|
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.QuickLayoutSwitch}"
|
||||||
|
Margin="{StaticResource XSmallTopMargin}"
|
||||||
|
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"/>
|
||||||
|
|
||||||
|
<CheckBox x:Uid="FancyZones_FlashZonesOnQuickSwitch"
|
||||||
|
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.FlashZonesOnQuickSwitch}"
|
||||||
|
Margin="24,8,0,0"
|
||||||
|
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.QuickSwitchEnabled}"/>
|
||||||
|
|
||||||
<TextBlock x:Uid="Appearance_GroupSettings"
|
<TextBlock x:Uid="Appearance_GroupSettings"
|
||||||
Style="{StaticResource SettingsGroupTitleStyle}"
|
Style="{StaticResource SettingsGroupTitleStyle}"
|
||||||
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled, Converter={StaticResource ModuleEnabledToForegroundConverter}}"/>
|
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled, Converter={StaticResource ModuleEnabledToForegroundConverter}}"/>
|
||||||
|
Loading…
Reference in New Issue
Block a user