[ColorPicker]Add option to choose what clicking individual mouse buttons does (#39025)

## Summary of the Pull Request
Enables the users to choose what left, right, and middle click does when
color picker is open.
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] **Closes:** #39006
- [x] **Communication:** I've discussed this with core contributors
already
- [x] **Tests:** All pass
- [x] **Localization:** All end user facing strings can be localized
- [x] **Dev docs:** No need
- [x] **New binaries:** None
- [x] **Documentation updated:** No need
## Detailed Description of the Pull Request / Additional comments
![Screenshot of the
settings](https://github.com/user-attachments/assets/a3e1349b-6bb9-4e2f-97f3-a5106a7d92ce)
Adds option to choose from 3 click behaviors for each standard mouse
button:
* **Pick color and open editor**: Copies color to clipboard, saves it to
the color history and opens the editor
* **Pick color and close**: Copies color to clipboard, saves it to the
color history and exits
* **Close**: Closes color picker without copying the color

Pressing <kbd>Enter</kbd> or <kbd>Space</kbd> does what clicking the
primary button would.
Left and middle click actions execute on mouse down, right click on
mouse up for reasons discussed previously (I can't find the conversation
now)
Default settings are chosen in such a way that very little or nothing
changes by updating.
## Validation Steps Performed
Tested:
* Migrating settings from v2.0 to v2.1 (v1 to v2.1 not tested)
* Settings page displays and saves settings correctly
* Default settings load correctly
* All three click actions do what they are supposed to
* Activation behavior works as expected, doesn't affect click actions
This commit is contained in:
PesBandi
2025-06-13 12:01:40 +02:00
committed by GitHub
parent 2d1676b7df
commit ce058f1dc7
17 changed files with 291 additions and 66 deletions

View File

@@ -910,6 +910,7 @@ metafile
mfc mfc
Mgmt Mgmt
Microwaved Microwaved
middleclickaction
midl midl
mii mii
mindaro mindaro
@@ -1251,6 +1252,7 @@ prg
prgh prgh
prgms prgms
pri pri
primaryclickaction
PRINTCLIENT PRINTCLIENT
printmanagement printmanagement
prm prm
@@ -1426,6 +1428,7 @@ SDKDDK
sdns sdns
searchterm searchterm
SEARCHUI SEARCHUI
secondaryclickaction
SECONDARYDISPLAY SECONDARYDISPLAY
secpol secpol
securestring securestring

View File

@@ -107,21 +107,14 @@ namespace ColorPicker.Helpers
} }
} }
public void OnColorPickerMouseDown() public void OpenColorEditor()
{ {
if (_userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenColorPickerAndThenEditor || _userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenEditor) lock (_colorPickerVisibilityLock)
{ {
lock (_colorPickerVisibilityLock) HideColorPicker();
{ }
HideColorPicker();
}
ShowColorPickerEditor(); ShowColorPickerEditor();
}
else
{
EndUserSession();
}
} }
public static void SetTopMost() public static void SetTopMost()

View File

@@ -16,10 +16,12 @@ namespace ColorPicker.Mouse
// position and bool indicating zoom in or zoom out // position and bool indicating zoom in or zoom out
event EventHandler<Tuple<System.Windows.Point, bool>> OnMouseWheel; event EventHandler<Tuple<System.Windows.Point, bool>> OnMouseWheel;
event MouseUpEventHandler OnMouseDown; event PrimaryMouseDownEventHandler OnPrimaryMouseDown;
event SecondaryMouseUpEventHandler OnSecondaryMouseUp; event SecondaryMouseUpEventHandler OnSecondaryMouseUp;
event MiddleMouseDownEventHandler OnMiddleMouseDown;
System.Windows.Point CurrentPosition { get; } System.Windows.Point CurrentPosition { get; }
Color CurrentColor { get; } Color CurrentColor { get; }

View File

@@ -7,17 +7,18 @@ using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Windows.Input; using System.Windows.Input;
using ColorPicker.Helpers;
using ManagedCommon; using ManagedCommon;
using static ColorPicker.NativeMethods; using static ColorPicker.NativeMethods;
namespace ColorPicker.Mouse namespace ColorPicker.Mouse
{ {
public delegate void MouseUpEventHandler(object sender, System.Drawing.Point p); public delegate void PrimaryMouseDownEventHandler(object sender, IntPtr wParam);
public delegate void SecondaryMouseUpEventHandler(object sender, IntPtr wParam); public delegate void SecondaryMouseUpEventHandler(object sender, IntPtr wParam);
public delegate void MiddleMouseDownEventHandler(object sender, IntPtr wParam);
internal class MouseHook internal class MouseHook
{ {
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Interop object")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Interop object")]
@@ -30,23 +31,25 @@ namespace ColorPicker.Mouse
private const int WM_RBUTTONUP = 0x0205; private const int WM_RBUTTONUP = 0x0205;
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Interop object")] [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Interop object")]
private const int WM_RBUTTONDOWN = 0x0204; private const int WM_RBUTTONDOWN = 0x0204;
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Interop object")]
private const int WM_MBUTTONDOWN = 0x0207;
private IntPtr _mouseHookHandle; private IntPtr _mouseHookHandle;
private HookProc _mouseDelegate; private HookProc _mouseDelegate;
private event MouseUpEventHandler MouseDown; private event PrimaryMouseDownEventHandler PrimaryMouseDown;
public event MouseUpEventHandler OnMouseDown public event PrimaryMouseDownEventHandler OnPrimaryMouseDown
{ {
add add
{ {
Subscribe(); Subscribe();
MouseDown += value; PrimaryMouseDown += value;
} }
remove remove
{ {
MouseDown -= value; PrimaryMouseDown -= value;
Unsubscribe(); Unsubscribe();
} }
} }
@@ -68,6 +71,23 @@ namespace ColorPicker.Mouse
} }
} }
private event MiddleMouseDownEventHandler MiddleMouseDown;
public event MiddleMouseDownEventHandler OnMiddleMouseDown
{
add
{
Subscribe();
MiddleMouseDown += value;
}
remove
{
MiddleMouseDown -= value;
Unsubscribe();
}
}
private event MouseWheelEventHandler MouseWheel; private event MouseWheelEventHandler MouseWheel;
public event MouseWheelEventHandler OnMouseWheel public event MouseWheelEventHandler OnMouseWheel
@@ -126,9 +146,9 @@ namespace ColorPicker.Mouse
MSLLHOOKSTRUCT mouseHookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)); MSLLHOOKSTRUCT mouseHookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
if (wParam.ToInt32() == WM_LBUTTONDOWN) if (wParam.ToInt32() == WM_LBUTTONDOWN)
{ {
if (MouseDown != null) if (PrimaryMouseDown != null)
{ {
MouseDown.Invoke(null, new System.Drawing.Point(mouseHookStruct.pt.x, mouseHookStruct.pt.y)); PrimaryMouseDown.Invoke(null, wParam);
} }
return new IntPtr(-1); return new IntPtr(-1);
@@ -150,6 +170,16 @@ namespace ColorPicker.Mouse
return new IntPtr(-1); return new IntPtr(-1);
} }
if (wParam.ToInt32() == WM_MBUTTONDOWN)
{
if (MiddleMouseDown != null)
{
MiddleMouseDown.Invoke(null, wParam);
}
return new IntPtr(-1);
}
if (wParam.ToInt32() == WM_MOUSEWHEEL) if (wParam.ToInt32() == WM_MOUSEWHEEL)
{ {
if (MouseWheel != null) if (MouseWheel != null)

View File

@@ -56,10 +56,12 @@ namespace ColorPicker.Mouse
public event EventHandler<Tuple<System.Windows.Point, bool>> OnMouseWheel; public event EventHandler<Tuple<System.Windows.Point, bool>> OnMouseWheel;
public event MouseUpEventHandler OnMouseDown; public event PrimaryMouseDownEventHandler OnPrimaryMouseDown;
public event SecondaryMouseUpEventHandler OnSecondaryMouseUp; public event SecondaryMouseUpEventHandler OnSecondaryMouseUp;
public event MiddleMouseDownEventHandler OnMiddleMouseDown;
public System.Windows.Point CurrentPosition public System.Windows.Point CurrentPosition
{ {
get get
@@ -148,9 +150,10 @@ namespace ColorPicker.Mouse
_timer.Start(); _timer.Start();
} }
_mouseHook.OnMouseDown += MouseHook_OnMouseDown; _mouseHook.OnPrimaryMouseDown += MouseHook_OnPrimaryMouseDown;
_mouseHook.OnMouseWheel += MouseHook_OnMouseWheel; _mouseHook.OnMouseWheel += MouseHook_OnMouseWheel;
_mouseHook.OnSecondaryMouseUp += MouseHook_OnSecondaryMouseUp; _mouseHook.OnSecondaryMouseUp += MouseHook_OnSecondaryMouseUp;
_mouseHook.OnMiddleMouseDown += MouseHook_OnMiddleMouseDown;
if (_userSettings.ChangeCursor.Value) if (_userSettings.ChangeCursor.Value)
{ {
@@ -169,10 +172,10 @@ namespace ColorPicker.Mouse
OnMouseWheel?.Invoke(this, new Tuple<System.Windows.Point, bool>(_previousMousePosition, zoomIn)); OnMouseWheel?.Invoke(this, new Tuple<System.Windows.Point, bool>(_previousMousePosition, zoomIn));
} }
private void MouseHook_OnMouseDown(object sender, Point p) private void MouseHook_OnPrimaryMouseDown(object sender, IntPtr wParam)
{ {
DisposeHook(); DisposeHook();
OnMouseDown?.Invoke(this, p); OnPrimaryMouseDown?.Invoke(this, wParam);
} }
private void MouseHook_OnSecondaryMouseUp(object sender, IntPtr wParam) private void MouseHook_OnSecondaryMouseUp(object sender, IntPtr wParam)
@@ -181,6 +184,12 @@ namespace ColorPicker.Mouse
OnSecondaryMouseUp?.Invoke(this, wParam); OnSecondaryMouseUp?.Invoke(this, wParam);
} }
private void MouseHook_OnMiddleMouseDown(object sender, IntPtr wParam)
{
DisposeHook();
OnMiddleMouseDown?.Invoke(this, wParam);
}
private void CopiedColorRepresentation_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) private void CopiedColorRepresentation_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{ {
_colorFormatChanged = true; _colorFormatChanged = true;
@@ -194,9 +203,10 @@ namespace ColorPicker.Mouse
} }
_previousMousePosition = new System.Windows.Point(-1, 1); _previousMousePosition = new System.Windows.Point(-1, 1);
_mouseHook.OnMouseDown -= MouseHook_OnMouseDown; _mouseHook.OnPrimaryMouseDown -= MouseHook_OnPrimaryMouseDown;
_mouseHook.OnMouseWheel -= MouseHook_OnMouseWheel; _mouseHook.OnMouseWheel -= MouseHook_OnMouseWheel;
_mouseHook.OnSecondaryMouseUp -= MouseHook_OnSecondaryMouseUp; _mouseHook.OnSecondaryMouseUp -= MouseHook_OnSecondaryMouseUp;
_mouseHook.OnMiddleMouseDown -= MouseHook_OnMiddleMouseDown;
if (_userSettings.ChangeCursor.Value) if (_userSettings.ChangeCursor.Value)
{ {

View File

@@ -21,6 +21,12 @@ namespace ColorPicker.Settings
SettingItem<ColorPickerActivationAction> ActivationAction { get; } SettingItem<ColorPickerActivationAction> ActivationAction { get; }
SettingItem<ColorPickerClickAction> PrimaryClickAction { get; }
SettingItem<ColorPickerClickAction> MiddleClickAction { get; }
SettingItem<ColorPickerClickAction> SecondaryClickAction { get; }
RangeObservableCollection<string> ColorHistory { get; } RangeObservableCollection<string> ColorHistory { get; }
SettingItem<int> ColorHistoryLimit { get; } SettingItem<int> ColorHistoryLimit { get; }

View File

@@ -49,7 +49,10 @@ namespace ColorPicker.Settings
ChangeCursor = new SettingItem<bool>(true); ChangeCursor = new SettingItem<bool>(true);
ActivationShortcut = new SettingItem<string>(DefaultActivationShortcut); ActivationShortcut = new SettingItem<string>(DefaultActivationShortcut);
CopiedColorRepresentation = new SettingItem<string>(ColorRepresentationType.HEX.ToString()); CopiedColorRepresentation = new SettingItem<string>(ColorRepresentationType.HEX.ToString());
ActivationAction = new SettingItem<ColorPickerActivationAction>(ColorPickerActivationAction.OpenEditor); ActivationAction = new SettingItem<ColorPickerActivationAction>(ColorPickerActivationAction.OpenColorPicker);
PrimaryClickAction = new SettingItem<ColorPickerClickAction>(ColorPickerClickAction.PickColorThenEditor);
MiddleClickAction = new SettingItem<ColorPickerClickAction>(ColorPickerClickAction.PickColorAndClose);
SecondaryClickAction = new SettingItem<ColorPickerClickAction>(ColorPickerClickAction.Close);
ColorHistoryLimit = new SettingItem<int>(20); ColorHistoryLimit = new SettingItem<int>(20);
ColorHistory.CollectionChanged += ColorHistory_CollectionChanged; ColorHistory.CollectionChanged += ColorHistory_CollectionChanged;
ShowColorName = new SettingItem<bool>(false); ShowColorName = new SettingItem<bool>(false);
@@ -78,6 +81,12 @@ namespace ColorPicker.Settings
public SettingItem<ColorPickerActivationAction> ActivationAction { get; private set; } public SettingItem<ColorPickerActivationAction> ActivationAction { get; private set; }
public SettingItem<ColorPickerClickAction> PrimaryClickAction { get; private set; }
public SettingItem<ColorPickerClickAction> MiddleClickAction { get; private set; }
public SettingItem<ColorPickerClickAction> SecondaryClickAction { get; private set; }
public RangeObservableCollection<string> ColorHistory { get; private set; } = new RangeObservableCollection<string>(); public RangeObservableCollection<string> ColorHistory { get; private set; } = new RangeObservableCollection<string>();
public SettingItem<int> ColorHistoryLimit { get; } public SettingItem<int> ColorHistoryLimit { get; }
@@ -121,6 +130,9 @@ namespace ColorPicker.Settings
CopiedColorRepresentation.Value = settings.Properties.CopiedColorRepresentation; CopiedColorRepresentation.Value = settings.Properties.CopiedColorRepresentation;
CopiedColorRepresentationFormat = new SettingItem<string>(string.Empty); CopiedColorRepresentationFormat = new SettingItem<string>(string.Empty);
ActivationAction.Value = settings.Properties.ActivationAction; ActivationAction.Value = settings.Properties.ActivationAction;
PrimaryClickAction.Value = settings.Properties.PrimaryClickAction;
MiddleClickAction.Value = settings.Properties.MiddleClickAction;
SecondaryClickAction.Value = settings.Properties.SecondaryClickAction;
ColorHistoryLimit.Value = settings.Properties.ColorHistoryLimit; ColorHistoryLimit.Value = settings.Properties.ColorHistoryLimit;
ShowColorName.Value = settings.Properties.ShowColorName; ShowColorName.Value = settings.Properties.ShowColorName;

View File

@@ -16,6 +16,7 @@ using ColorPicker.Settings;
using ColorPicker.ViewModelContracts; using ColorPicker.ViewModelContracts;
using Common.UI; using Common.UI;
using ManagedCommon; using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
using PowerToys.Interop; using PowerToys.Interop;
namespace ColorPicker.ViewModels namespace ColorPicker.ViewModels
@@ -79,9 +80,10 @@ namespace ColorPicker.ViewModels
{ {
SetColorDetails(mouseInfoProvider.CurrentColor); SetColorDetails(mouseInfoProvider.CurrentColor);
mouseInfoProvider.MouseColorChanged += Mouse_ColorChanged; mouseInfoProvider.MouseColorChanged += Mouse_ColorChanged;
mouseInfoProvider.OnMouseDown += MouseInfoProvider_OnMouseDown; mouseInfoProvider.OnPrimaryMouseDown += MouseInfoProvider_OnPrimaryMouseDown;
mouseInfoProvider.OnMouseWheel += MouseInfoProvider_OnMouseWheel; mouseInfoProvider.OnMouseWheel += MouseInfoProvider_OnMouseWheel;
mouseInfoProvider.OnSecondaryMouseUp += MouseInfoProvider_OnSecondaryMouseUp; mouseInfoProvider.OnSecondaryMouseUp += MouseInfoProvider_OnSecondaryMouseUp;
mouseInfoProvider.OnMiddleMouseDown += MouseInfoProvider_OnMiddleMouseDown;
} }
_userSettings.ShowColorName.PropertyChanged += (s, e) => { OnPropertyChanged(nameof(ShowColorName)); }; _userSettings.ShowColorName.PropertyChanged += (s, e) => { OnPropertyChanged(nameof(ShowColorName)); };
@@ -113,7 +115,7 @@ namespace ColorPicker.ViewModels
private void AppStateHandler_EnterPressed(object sender, EventArgs e) private void AppStateHandler_EnterPressed(object sender, EventArgs e)
{ {
MouseInfoProvider_OnMouseDown(null, default(System.Drawing.Point)); MouseInfoProvider_OnPrimaryMouseDown(null, default);
} }
/// <summary> /// <summary>
@@ -167,18 +169,50 @@ namespace ColorPicker.ViewModels
SetColorDetails(color); SetColorDetails(color);
} }
/// <summary> private void MouseInfoProvider_OnPrimaryMouseDown(object sender, IntPtr wParam)
/// Tell the color picker that the user have press a mouse button (after release the button)
/// </summary>
/// <param name="sender">The sender of this event</param>
/// <param name="p">The current <see cref="System.Drawing.Point"/> of the mouse cursor</param>
private void MouseInfoProvider_OnMouseDown(object sender, System.Drawing.Point p)
{ {
ClipboardHelper.CopyToClipboard(ColorText); HandleMouseClickAction(_userSettings.PrimaryClickAction.Value);
}
var color = GetColorString(); private void MouseInfoProvider_OnMiddleMouseDown(object sender, IntPtr wParam)
{
HandleMouseClickAction(_userSettings.MiddleClickAction.Value);
}
var oldIndex = _userSettings.ColorHistory.IndexOf(color); private void MouseInfoProvider_OnSecondaryMouseUp(object sender, IntPtr wParam)
{
HandleMouseClickAction(_userSettings.SecondaryClickAction.Value);
}
private void HandleMouseClickAction(ColorPickerClickAction action)
{
switch (action)
{
case ColorPickerClickAction.PickColorThenEditor:
ClipboardHelper.CopyToClipboard(ColorText);
UpdateColorHistory(GetColorString());
_appStateHandler.OpenColorEditor();
break;
case ColorPickerClickAction.PickColorAndClose:
ClipboardHelper.CopyToClipboard(ColorText);
UpdateColorHistory(GetColorString());
_appStateHandler.EndUserSession();
break;
case ColorPickerClickAction.Close:
_appStateHandler.EndUserSession();
break;
}
}
private void UpdateColorHistory(string color)
{
int oldIndex = _userSettings.ColorHistory.IndexOf(color);
if (oldIndex != -1) if (oldIndex != -1)
{ {
_userSettings.ColorHistory.Move(oldIndex, 0); _userSettings.ColorHistory.Move(oldIndex, 0);
@@ -192,13 +226,6 @@ namespace ColorPicker.ViewModels
{ {
_userSettings.ColorHistory.RemoveAt(_userSettings.ColorHistory.Count - 1); _userSettings.ColorHistory.RemoveAt(_userSettings.ColorHistory.Count - 1);
} }
_appStateHandler.OnColorPickerMouseDown();
}
private void MouseInfoProvider_OnSecondaryMouseUp(object sender, IntPtr wParam)
{
_appStateHandler.EndUserSession();
} }
private string GetColorString() private string GetColorString()

View File

@@ -40,7 +40,10 @@ namespace Microsoft.PowerToys.Settings.UI.Library
VisibleColorFormats.Add("Decimal", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("Decimal"))); VisibleColorFormats.Add("Decimal", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("Decimal")));
VisibleColorFormats.Add("HEX Int", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("HEX Int"))); VisibleColorFormats.Add("HEX Int", new KeyValuePair<bool, string>(false, ColorFormatHelper.GetDefaultFormat("HEX Int")));
ShowColorName = false; ShowColorName = false;
ActivationAction = ColorPickerActivationAction.OpenColorPickerAndThenEditor; ActivationAction = ColorPickerActivationAction.OpenColorPicker;
PrimaryClickAction = ColorPickerClickAction.PickColorThenEditor;
MiddleClickAction = ColorPickerClickAction.PickColorAndClose;
SecondaryClickAction = ColorPickerClickAction.Close;
CopiedColorRepresentation = "HEX"; CopiedColorRepresentation = "HEX";
} }
@@ -57,6 +60,15 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[JsonPropertyName("activationaction")] [JsonPropertyName("activationaction")]
public ColorPickerActivationAction ActivationAction { get; set; } public ColorPickerActivationAction ActivationAction { get; set; }
[JsonPropertyName("primaryclickaction")]
public ColorPickerClickAction PrimaryClickAction { get; set; }
[JsonPropertyName("middleclickaction")]
public ColorPickerClickAction MiddleClickAction { get; set; }
[JsonPropertyName("secondaryclickaction")]
public ColorPickerClickAction SecondaryClickAction { get; set; }
// Property ColorHistory is not used, the color history is saved separately in the colorHistory.json file // Property ColorHistory is not used, the color history is saved separately in the colorHistory.json file
[JsonPropertyName("colorhistory")] [JsonPropertyName("colorhistory")]
[CmdConfigureIgnoreAttribute] [CmdConfigureIgnoreAttribute]

View File

@@ -25,7 +25,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
VisibleColorFormats.Add("RGB", true); VisibleColorFormats.Add("RGB", true);
VisibleColorFormats.Add("HSL", true); VisibleColorFormats.Add("HSL", true);
ShowColorName = false; ShowColorName = false;
ActivationAction = ColorPickerActivationAction.OpenColorPickerAndThenEditor; ActivationAction = ColorPickerActivationAction.OpenColorPicker;
} }
public HotkeySettings ActivationShortcut { get; set; } public HotkeySettings ActivationShortcut { get; set; }

View File

@@ -9,6 +9,7 @@ using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using ManagedCommon; using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces; using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library namespace Microsoft.PowerToys.Settings.UI.Library
@@ -23,7 +24,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
public ColorPickerSettings() public ColorPickerSettings()
{ {
Properties = new ColorPickerProperties(); Properties = new ColorPickerProperties();
Version = "2"; Version = "2.1";
Name = ModuleName; Name = ModuleName;
} }
@@ -47,7 +48,21 @@ namespace Microsoft.PowerToys.Settings.UI.Library
// This can be utilized in the future if the settings.json file is to be modified/deleted. // This can be utilized in the future if the settings.json file is to be modified/deleted.
public bool UpgradeSettingsConfiguration() public bool UpgradeSettingsConfiguration()
=> false; {
// Upgrading V1 to V2 doesn't set the version to 2.0, therefore V2 settings still report Version == 1.0
if (Version == "1.0")
{
if (!Enum.IsDefined(Properties.ActivationAction))
{
Properties.ActivationAction = ColorPickerActivationAction.OpenColorPicker;
}
Version = "2.1";
return true;
}
return false;
}
public static object UpgradeSettings(object oldSettingsObject) public static object UpgradeSettings(object oldSettingsObject)
{ {

View File

@@ -9,10 +9,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Enumerations
// Activation shortcut opens editor // Activation shortcut opens editor
OpenEditor, OpenEditor,
// Activation shortcut opens color picker and after picking a color is copied into clipboard and opens editor // Activation shortcut opens color picker and after picking a color is copied into clipboard and editor optionally opens depending on which mouse button was pressed
OpenColorPickerAndThenEditor, OpenColorPicker,
// Activation shortcut opens color picker only and picking color copies color into clipboard
OpenOnlyColorPicker,
} }
} }

View File

@@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.PowerToys.Settings.UI.Library.Enumerations
{
public enum ColorPickerClickAction
{
// Clicking copies the picked color and opens the editor
PickColorThenEditor,
// Clicking only copies the picked color and then exits color picker
PickColorAndClose,
// Clicking exits color picker, without copying anything
Close,
}
}

View File

@@ -130,6 +130,13 @@ namespace Microsoft.PowerToys.Settings.UI.Library
T2 oldSettings = GetSettings<T2>(powertoy, fileName); T2 oldSettings = GetSettings<T2>(powertoy, fileName);
T newSettings = (T)settingsUpgrader(oldSettings); T newSettings = (T)settingsUpgrader(oldSettings);
Logger.LogInfo($"Settings file {fileName} for {powertoy} was read successfully in the old format."); Logger.LogInfo($"Settings file {fileName} for {powertoy} was read successfully in the old format.");
// If the file needs to be modified, to save the new configurations accordingly.
if (newSettings.UpgradeSettingsConfiguration())
{
SaveSettings(newSettings.ToJsonString(), powertoy, fileName);
}
return newSettings; return newSettings;
} }
catch (Exception) catch (Exception)

View File

@@ -50,12 +50,39 @@
<tkcontrols:SettingsCard x:Uid="ColorPicker_ActivationAction" HeaderIcon="{ui:FontIcon Glyph=&#xEC4E;}"> <tkcontrols:SettingsCard x:Uid="ColorPicker_ActivationAction" HeaderIcon="{ui:FontIcon Glyph=&#xEC4E;}">
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind Path=ViewModel.ActivationBehavior, Mode=TwoWay}"> <ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind Path=ViewModel.ActivationBehavior, Mode=TwoWay}">
<ComboBoxItem x:Uid="EditorFirst" /> <ComboBoxItem x:Uid="ColorPicker_OpenEditor" />
<ComboBoxItem x:Uid="ColorPickerFirst" /> <ComboBoxItem x:Uid="ColorPicker_PickColor" />
<ComboBoxItem x:Uid="ColorPickerOnly" />
</ComboBox> </ComboBox>
</tkcontrols:SettingsCard> </tkcontrols:SettingsCard>
<tkcontrols:SettingsExpander
x:Uid="ColorPicker_MouseActions"
HeaderIcon="{ui:FontIcon Glyph=&#xE962;}"
IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsExpander.Items>
<tkcontrols:SettingsCard x:Uid="ColorPicker_PrimaryClick" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind ViewModel.PrimaryClickBehavior, Mode=TwoWay}">
<ComboBoxItem x:Uid="ColorPicker_PickColorThenEditor" />
<ComboBoxItem x:Uid="ColorPicker_PickColorAndClose" />
<ComboBoxItem x:Uid="ColorPicker_Close" />
</ComboBox>
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard x:Uid="ColorPicker_MiddleClick" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind ViewModel.MiddleClickBehavior, Mode=TwoWay}">
<ComboBoxItem x:Uid="ColorPicker_PickColorThenEditor" />
<ComboBoxItem x:Uid="ColorPicker_PickColorAndClose" />
<ComboBoxItem x:Uid="ColorPicker_Close" />
</ComboBox>
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard x:Uid="ColorPicker_SecondaryClick" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind ViewModel.SecondaryClickBehavior, Mode=TwoWay}">
<ComboBoxItem x:Uid="ColorPicker_PickColorThenEditor" />
<ComboBoxItem x:Uid="ColorPicker_PickColorAndClose" />
<ComboBoxItem x:Uid="ColorPicker_Close" />
</ComboBox>
</tkcontrols:SettingsCard>
</tkcontrols:SettingsExpander.Items>
</tkcontrols:SettingsExpander>
</controls:SettingsGroup> </controls:SettingsGroup>
<controls:SettingsGroup x:Uid="ColorFormats" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}"> <controls:SettingsGroup x:Uid="ColorFormats" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">

View File

@@ -1507,18 +1507,39 @@ Made with 💗 by Microsoft and the PowerToys community.</value>
<data name="ColorPicker_CopiedColorRepresentation.Header" xml:space="preserve"> <data name="ColorPicker_CopiedColorRepresentation.Header" xml:space="preserve">
<value>Default color format</value> <value>Default color format</value>
</data> </data>
<data name="ColorPickerFirst.Content" xml:space="preserve">
<value>Pick a color and open editor</value>
</data>
<data name="EditorFirst.Content" xml:space="preserve">
<value>Open editor</value>
</data>
<data name="ColorPickerOnly.Content" xml:space="preserve">
<value>Only pick a color</value>
</data>
<data name="ColorPicker_ActivationAction.Header" xml:space="preserve"> <data name="ColorPicker_ActivationAction.Header" xml:space="preserve">
<value>Activation behavior</value> <value>Activation behavior</value>
</data> </data>
<data name="ColorPicker_OpenEditor.Content" xml:space="preserve">
<value>Open editor</value>
</data>
<data name="ColorPicker_PickColor.Content" xml:space="preserve">
<value>Pick a color first</value>
</data>
<data name="ColorPicker_MouseActions.Header" xml:space="preserve">
<value>Mouse actions</value>
</data>
<data name="ColorPicker_MouseActions.Description" xml:space="preserve">
<value>Choose what clicking individual buttons does</value>
</data>
<data name="ColorPicker_PrimaryClick.Header" xml:space="preserve">
<value>Primary click</value>
</data>
<data name="ColorPicker_MiddleClick.Header" xml:space="preserve">
<value>Middle click</value>
</data>
<data name="ColorPicker_SecondaryClick.Header" xml:space="preserve">
<value>Secondary click</value>
</data>
<data name="ColorPicker_PickColorThenEditor.Content" xml:space="preserve">
<value>Pick a color and open editor</value>
</data>
<data name="ColorPicker_PickColorAndClose.Content" xml:space="preserve">
<value>Pick a color and close</value>
</data>
<data name="ColorPicker_Close.Content" xml:space="preserve">
<value>Close</value>
</data>
<data name="ColorFormats.Header" xml:space="preserve"> <data name="ColorFormats.Header" xml:space="preserve">
<value>Picker behavior</value> <value>Picker behavior</value>
</data> </data>

View File

@@ -182,6 +182,51 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
} }
} }
public int PrimaryClickBehavior
{
get => (int)_colorPickerSettings.Properties.PrimaryClickAction;
set
{
if (value != (int)_colorPickerSettings.Properties.PrimaryClickAction)
{
_colorPickerSettings.Properties.PrimaryClickAction = (ColorPickerClickAction)value;
OnPropertyChanged(nameof(PrimaryClickBehavior));
NotifySettingsChanged();
}
}
}
public int MiddleClickBehavior
{
get => (int)_colorPickerSettings.Properties.MiddleClickAction;
set
{
if (value != (int)_colorPickerSettings.Properties.MiddleClickAction)
{
_colorPickerSettings.Properties.MiddleClickAction = (ColorPickerClickAction)value;
OnPropertyChanged(nameof(MiddleClickBehavior));
NotifySettingsChanged();
}
}
}
public int SecondaryClickBehavior
{
get => (int)_colorPickerSettings.Properties.SecondaryClickAction;
set
{
if (value != (int)_colorPickerSettings.Properties.SecondaryClickAction)
{
_colorPickerSettings.Properties.SecondaryClickAction = (ColorPickerClickAction)value;
OnPropertyChanged(nameof(SecondaryClickBehavior));
NotifySettingsChanged();
}
}
}
public bool ShowColorName public bool ShowColorName
{ {
get => _colorPickerSettings.Properties.ShowColorName; get => _colorPickerSettings.Properties.ShowColorName;