diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.cs b/src/modules/MouseWithoutBorders/App/Class/Common.cs index d087ca59af..4731eb9cfe 100644 --- a/src/modules/MouseWithoutBorders/App/Class/Common.cs +++ b/src/modules/MouseWithoutBorders/App/Class/Common.cs @@ -17,6 +17,7 @@ using System.Security.Cryptography; using System.Text; using System.Threading; using System.Windows.Forms; +using Microsoft.PowerToys.Settings.UI.Library; // // Most of the helper methods. @@ -115,6 +116,11 @@ namespace MouseWithoutBorders internal static Process CurrentProcess { get; set; } + internal static bool HotkeyMatched(int vkCode, bool winDown, bool ctrlDown, bool altDown, bool shiftDown, HotkeySettings hotkey) + { + return !hotkey.IsEmpty() && (vkCode == hotkey.Code) && (!hotkey.Win || winDown) && (!hotkey.Alt || altDown) && (!hotkey.Shift || shiftDown) && (!hotkey.Ctrl || ctrlDown); + } + public static string BinaryName { get => Common.binaryName; diff --git a/src/modules/MouseWithoutBorders/App/Class/InputHook.cs b/src/modules/MouseWithoutBorders/App/Class/InputHook.cs index 87a1068cb0..c9e8557aef 100644 --- a/src/modules/MouseWithoutBorders/App/Class/InputHook.cs +++ b/src/modules/MouseWithoutBorders/App/Class/InputHook.cs @@ -11,11 +11,13 @@ // 2023- Included in PowerToys. // using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; using System.Runtime.InteropServices; using System.Windows.Forms; +using Microsoft.PowerToys.Settings.UI.Library; [module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.InputHook.#MouseHookProc(System.Int32,System.Int32,System.IntPtr)", Justification = "Dotnet port with style preservation")] [module: SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "MouseWithoutBorders.InputHook.#ProcessKeyEx(System.Int32,System.Int32)", Justification = "Dotnet port with style preservation")] @@ -364,17 +366,8 @@ namespace MouseWithoutBorders.Class } } - // Returns false if we do not want to redirect the keystrokes to other machine(s). - private int ctrlTouchesDnIndex; - - private int ctrlTouchesUpIndex = 1; - private const int CONTROL_TOUCH = 4; - private readonly long[] ctrlTouches = new long[CONTROL_TOUCH]; - private bool ProcessKeyEx(int vkCode, int flags, KEYBDDATA hookCallbackKeybdData) { - bool allTouched; - if ((flags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP) { EasyMouseKeyDown = false; @@ -389,13 +382,6 @@ namespace MouseWithoutBorders.Class case VK.LCONTROL: case VK.RCONTROL: CtrlDown = false; - - if (Setting.Values.HotKeySwitch2AllPC == 1) - { - ctrlTouches[ctrlTouchesUpIndex] = Common.GetTick(); - ctrlTouchesUpIndex = ((ctrlTouchesUpIndex % CONTROL_TOUCH) + 2) % CONTROL_TOUCH; - } - break; case VK.LMENU: @@ -424,32 +410,7 @@ namespace MouseWithoutBorders.Class case VK.LCONTROL: case VK.RCONTROL: - Common.LogDebug("VK.RCONTROL"); CtrlDown = true; - - if (Setting.Values.HotKeySwitch2AllPC == 1) - { - ctrlTouches[ctrlTouchesDnIndex] = Common.GetTick(); - ctrlTouchesDnIndex = (ctrlTouchesDnIndex + 2) % CONTROL_TOUCH; - } - - allTouched = true; - - for (int i = 0; i < CONTROL_TOUCH; i++) - { - if (ctrlTouches[i] == 0 || Common.GetTick() - ctrlTouches[i] > 400) - { - allTouched = false; - break; - } - } - - if (allTouched && Common.GetTick() - Common.JustGotAKey > 1000) - { - ResetLastSwitchKeys(); - Common.SwitchToMultipleMode(Common.DesMachineID != ID.ALL, true); - } - break; case VK.LMENU: @@ -484,24 +445,6 @@ namespace MouseWithoutBorders.Class break; - case (VK)'L': - if (winDown) - { - winDown = false; - - if (Common.DesMachineID != ID.ALL) - { - KeyboardEvent(hookCallbackKeybdData); - Common.SwitchToMachine(Common.MachineName.Trim()); - } - } - else - { - return ProcessHotKeys(vkCode, hookCallbackKeybdData); - } - - break; - case VK.ESCAPE: if (Common.IsTopMostMessageNotNull()) { @@ -529,19 +472,114 @@ namespace MouseWithoutBorders.Class private static long lastHotKeyLockMachine; + private void ResetModifiersState(HotkeySettings matchingHotkey) + { + CtrlDown = CtrlDown && matchingHotkey.Ctrl; + altDown = altDown && matchingHotkey.Alt; + shiftDown = shiftDown && matchingHotkey.Shift; + winDown = winDown && matchingHotkey.Win; + } + + private List GetVkCodesList(HotkeySettings hotkey) + { + var list = new List(); + if (hotkey.Alt) + { + list.Add((short)VK.MENU); + } + + if (hotkey.Shift) + { + list.Add((short)VK.SHIFT); + } + + if (hotkey.Win) + { + list.Add((short)VK.LWIN); + } + + if (hotkey.Ctrl) + { + list.Add((short)VK.CONTROL); + } + + if (hotkey.Code != 0) + { + list.Add((short)hotkey.Code); + } + + return list; + } + private bool ProcessHotKeys(int vkCode, KEYBDDATA hookCallbackKeybdData) { - if (vkCode == Setting.Values.HotKeyCaptureScreen && CtrlDown && shiftDown && !altDown && - (Common.DesMachineID == Common.MachineID || Common.DesMachineID == ID.ALL)) + if (Common.HotkeyMatched(vkCode, winDown, CtrlDown, altDown, shiftDown, Setting.Values.HotKeySwitch2AllPC)) { - CtrlDown = shiftDown = false; + ResetLastSwitchKeys(); + Common.SwitchToMultipleMode(Common.DesMachineID != ID.ALL, true); + } + if (Common.HotkeyMatched(vkCode, winDown, CtrlDown, altDown, shiftDown, Setting.Values.HotKeyToggleEasyMouse)) + { if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop) { - Common.PrepareScreenCapture(); + EasyMouseOption easyMouseOption = (EasyMouseOption)Setting.Values.EasyMouse; + + if (easyMouseOption is EasyMouseOption.Disable or EasyMouseOption.Enable) + { + Setting.Values.EasyMouse = (int)(easyMouseOption == EasyMouseOption.Disable ? EasyMouseOption.Enable : EasyMouseOption.Disable); + + Common.ShowToolTip($"Easy Mouse has been toggled to [{(EasyMouseOption)Setting.Values.EasyMouse}] by a hotkey. You can change the hotkey in the Settings form.", 5000); + return false; + } + } + } + else if (Common.HotkeyMatched(vkCode, winDown, CtrlDown, altDown, shiftDown, Setting.Values.HotKeyLockMachine)) + { + if (!Common.RunOnLogonDesktop + && !Common.RunOnScrSaverDesktop) + { + if (Common.GetTick() - lastHotKeyLockMachine < 500) + { + Common.SwitchToMultipleMode(true, true); + + var codes = GetVkCodesList(Setting.Values.HotKeyLockMachine); + + foreach (var code in codes) + { + hookCallbackKeybdData.wVk = code; + KeyboardEvent(hookCallbackKeybdData); + } + + hookCallbackKeybdData.dwFlags |= (int)Common.LLKHF.UP; + + foreach (var code in codes) + { + hookCallbackKeybdData.wVk = code; + KeyboardEvent(hookCallbackKeybdData); + } + + Common.SwitchToMultipleMode(false, true); + + _ = NativeMethods.LockWorkStation(); + } + else + { + KeyboardEvent(hookCallbackKeybdData); + } + + lastHotKeyLockMachine = Common.GetTick(); + return false; } } + else if (Common.HotkeyMatched(vkCode, winDown, CtrlDown, altDown, shiftDown, Setting.Values.HotKeyReconnect)) + { + Common.ShowToolTip("Reconnecting...", 2000); + Common.LastReconnectByHotKeyTime = Common.GetTick(); + Common.PleaseReopenSocket = Common.REOPEN_WHEN_HOTKEY; + return false; + } if (CtrlDown && altDown) { @@ -578,72 +616,6 @@ namespace MouseWithoutBorders.Class return false; } } - else if (vkCode == Setting.Values.HotKeyLockMachine) - { - if (!Common.RunOnLogonDesktop - && !Common.RunOnScrSaverDesktop) - { - if (Common.GetTick() - lastHotKeyLockMachine < 500) - { - Common.SwitchToMultipleMode(true, true); - - hookCallbackKeybdData.wVk = (short)VK.LCONTROL; - KeyboardEvent(hookCallbackKeybdData); - hookCallbackKeybdData.wVk = (short)VK.LMENU; - KeyboardEvent(hookCallbackKeybdData); - hookCallbackKeybdData.wVk = vkCode; - KeyboardEvent(hookCallbackKeybdData); - - hookCallbackKeybdData.dwFlags |= (int)Common.LLKHF.UP; - - hookCallbackKeybdData.wVk = (short)VK.LCONTROL; - KeyboardEvent(hookCallbackKeybdData); - hookCallbackKeybdData.wVk = (short)VK.LMENU; - KeyboardEvent(hookCallbackKeybdData); - hookCallbackKeybdData.wVk = vkCode; - KeyboardEvent(hookCallbackKeybdData); - - Common.SwitchToMultipleMode(false, true); - - _ = NativeMethods.LockWorkStation(); - } - else - { - KeyboardEvent(hookCallbackKeybdData); - } - - lastHotKeyLockMachine = Common.GetTick(); - - return false; - } - } - else if (vkCode == Setting.Values.HotKeyReconnect) - { - Common.ShowToolTip("Reconnecting...", 2000); - Common.LastReconnectByHotKeyTime = Common.GetTick(); - Common.PleaseReopenSocket = Common.REOPEN_WHEN_HOTKEY; - return false; - } - else if (vkCode == Setting.Values.HotKeySwitch2AllPC) - { - Common.SwitchToMultipleMode(Common.DesMachineID != ID.ALL, true); - return false; - } - else if (vkCode == Setting.Values.HotKeyToggleEasyMouse) - { - if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop) - { - EasyMouseOption easyMouseOption = (EasyMouseOption)Setting.Values.EasyMouse; - - if (easyMouseOption is EasyMouseOption.Disable or EasyMouseOption.Enable) - { - Setting.Values.EasyMouse = (int)(easyMouseOption == EasyMouseOption.Disable ? EasyMouseOption.Enable : EasyMouseOption.Disable); - - Common.ShowToolTip($"Easy Mouse has been toggled to [{(EasyMouseOption)Setting.Values.EasyMouse}] by a hotkey. You can change the hotkey in the Settings form.", 5000); - return false; - } - } - } } return true; @@ -685,11 +657,6 @@ namespace MouseWithoutBorders.Class internal void ResetLastSwitchKeys() { - for (int i = 0; i < CONTROL_TOUCH; i++) - { - ctrlTouches[i] = 0; - } - CtrlDown = winDown = altDown = false; } } diff --git a/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs b/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs index 220da7454e..adb0c90bd0 100644 --- a/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs +++ b/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs @@ -15,6 +15,7 @@ using System.Globalization; using System.Runtime.InteropServices; using System.ServiceProcess; using System.Threading.Tasks; +using Microsoft.PowerToys.Settings.UI.Library; using Windows.UI.Input.Preview.Injection; using static MouseWithoutBorders.Class.NativeMethods; @@ -353,6 +354,14 @@ namespace MouseWithoutBorders.Class private static bool altDown; private static bool shiftDown; + private static void ResetModifiersState(HotkeySettings matchingHotkey) + { + ctrlDown = ctrlDown && matchingHotkey.Ctrl; + altDown = altDown && matchingHotkey.Alt; + shiftDown = shiftDown && matchingHotkey.Shift; + winDown = winDown && matchingHotkey.Win; + } + private static void InputProcessKeyEx(int vkCode, int flags, out bool eatKey) { eatKey = false; @@ -387,28 +396,15 @@ namespace MouseWithoutBorders.Class } else { - if (vkCode == Setting.Values.HotKeyLockMachine) + if (Common.HotkeyMatched(vkCode, winDown, ctrlDown, altDown, shiftDown, Setting.Values.HotKeyLockMachine)) { if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop) { - if (ctrlDown && altDown) - { - ctrlDown = altDown = false; - eatKey = true; - Common.ReleaseAllKeys(); - _ = NativeMethods.LockWorkStation(); - } - } - } - else if (vkCode == Setting.Values.HotKeyCaptureScreen && ctrlDown && shiftDown && !altDown) - { - ctrlDown = shiftDown = false; - - if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop) - { - Common.PrepareScreenCapture(); + ResetModifiersState(Setting.Values.HotKeyLockMachine); eatKey = true; + Common.ReleaseAllKeys(); + _ = NativeMethods.LockWorkStation(); } } diff --git a/src/modules/MouseWithoutBorders/App/Class/Setting.cs b/src/modules/MouseWithoutBorders/App/Class/Setting.cs index e3699a0766..46f647c151 100644 --- a/src/modules/MouseWithoutBorders/App/Class/Setting.cs +++ b/src/modules/MouseWithoutBorders/App/Class/Setting.cs @@ -648,13 +648,24 @@ namespace MouseWithoutBorders.Class } } - internal int HotKeyToggleEasyMouse + internal HotkeySettings HotKeySwitch2AllPC { get { lock (_loadingSettingsLock) { - return _properties.HotKeyToggleEasyMouse.Value; + return _properties.Switch2AllPCShortcut; + } + } + } + + internal HotkeySettings HotKeyToggleEasyMouse + { + get + { + lock (_loadingSettingsLock) + { + return _properties.ToggleEasyMouseShortcut; } } @@ -662,18 +673,18 @@ namespace MouseWithoutBorders.Class { lock (_loadingSettingsLock) { - _properties.HotKeyToggleEasyMouse.Value = value; + _properties.ToggleEasyMouseShortcut = value; } } } - internal int HotKeyLockMachine + internal HotkeySettings HotKeyLockMachine { get { lock (_loadingSettingsLock) { - return _properties.HotKeyLockMachine.Value; + return _properties.LockMachineShortcut; } } @@ -681,18 +692,18 @@ namespace MouseWithoutBorders.Class { lock (_loadingSettingsLock) { - _properties.HotKeyLockMachine.Value = value; + _properties.LockMachineShortcut = value; } } } - internal int HotKeyReconnect + internal HotkeySettings HotKeyReconnect { get { lock (_loadingSettingsLock) { - return _properties.HotKeyReconnect.Value; + return _properties.ReconnectShortcut; } } @@ -700,19 +711,11 @@ namespace MouseWithoutBorders.Class { lock (_loadingSettingsLock) { - _properties.HotKeyReconnect.Value = value; + _properties.ReconnectShortcut = value; } } } - internal int HotKeyCaptureScreen - { - get - { - return 0; - } - } - internal int HotKeyExitMM { get @@ -721,25 +724,6 @@ namespace MouseWithoutBorders.Class } } - internal int HotKeySwitch2AllPC - { - get - { - lock (_loadingSettingsLock) - { - return _properties.HotKeySwitch2AllPC.Value; - } - } - - set - { - lock (_loadingSettingsLock) - { - _properties.HotKeySwitch2AllPC.Value = value; - } - } - } - private int switchCount; internal int SwitchCount diff --git a/src/modules/MouseWithoutBorders/App/Form/frmMatrix.Designer.cs b/src/modules/MouseWithoutBorders/App/Form/frmMatrix.Designer.cs index 2f0e2c07a4..21697f490d 100644 --- a/src/modules/MouseWithoutBorders/App/Form/frmMatrix.Designer.cs +++ b/src/modules/MouseWithoutBorders/App/Form/frmMatrix.Designer.cs @@ -1,5 +1,6 @@ using System.Windows.Forms; using System.Collections.Generic; +using System.Drawing; namespace MouseWithoutBorders { @@ -713,6 +714,16 @@ namespace MouseWithoutBorders this.groupBoxShortcuts.TabIndex = 200; this.groupBoxShortcuts.TabStop = false; this.groupBoxShortcuts.Text = " &Keyboard Shortcuts "; + + + ToolTip groupBoxToolTip = new ToolTip(); + groupBoxToolTip.SetToolTip(this.groupBoxShortcuts, "These settings are controlled by the PowerToys.Settings application."); + + foreach (Control control in this.groupBoxShortcuts.Controls) + { + control.Enabled = false; + } + // // labelScreenCapture // diff --git a/src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs b/src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs index 20bd8917bf..c786498f97 100644 --- a/src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs +++ b/src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs @@ -830,13 +830,11 @@ namespace MouseWithoutBorders comboBoxShowSettings.Text = "Disable"; comboBoxExitMM.Text = Setting.Values.HotKeyExitMM == 0 ? "Disable" : new string(new char[] { (char)Setting.Values.HotKeyExitMM }); - +#if OBSOLETE_SHORTCUTS comboBoxLockMachine.Text = Setting.Values.HotKeyLockMachine == 0 ? "Disable" : new string(new char[] { (char)Setting.Values.HotKeyLockMachine }); comboBoxReconnect.Text = Setting.Values.HotKeyReconnect == 0 ? "Disable" : new string(new char[] { (char)Setting.Values.HotKeyReconnect }); - comboBoxScreenCapture.Text = Setting.Values.HotKeyCaptureScreen == 0 ? "Disable" : new string(new char[] { (char)Setting.Values.HotKeyCaptureScreen }); - comboBoxSwitchToAllPC.Text = Setting.Values.HotKeySwitch2AllPC == 1 ? "Ctrl*3" : Setting.Values.HotKeySwitch2AllPC == 0 ? "Disable" : new string(new char[] { (char)Setting.Values.HotKeySwitch2AllPC }); @@ -844,6 +842,7 @@ namespace MouseWithoutBorders comboBoxEasyMouseOption.Text = ((EasyMouseOption)Setting.Values.EasyMouse).ToString(); comboBoxEasyMouse.Text = Setting.Values.HotKeyToggleEasyMouse == 0 ? "Disable" : new string(new char[] { (char)Setting.Values.HotKeyToggleEasyMouse }); +#endif } private void RadioButton_CheckedChanged(object sender, EventArgs e) @@ -870,6 +869,7 @@ namespace MouseWithoutBorders private void ComboBoxLockMachine_TextChanged(object sender, EventArgs e) { +#if OBSOLETE_SHORTCUTS if (comboBoxLockMachine.Text.Contains("Disable")) { Setting.Values.HotKeyLockMachine = 0; @@ -878,10 +878,12 @@ namespace MouseWithoutBorders { Setting.Values.HotKeyLockMachine = comboBoxLockMachine.Text[0]; } +#endif } private void ComboBoxSwitchToAllPC_TextChanged(object sender, EventArgs e) { +#if OBSOLETE_SHORTCUTS if (comboBoxSwitchToAllPC.Text.Contains("Disable")) { Setting.Values.HotKeySwitch2AllPC = 0; @@ -894,7 +896,7 @@ namespace MouseWithoutBorders { Setting.Values.HotKeySwitch2AllPC = comboBoxSwitchToAllPC.Text[0]; } - +#endif ShowUpdateMessage(); } @@ -957,6 +959,7 @@ namespace MouseWithoutBorders private void ComboBoxReconnect_TextChanged(object sender, EventArgs e) { +#if OBSOLETE_SHORTCUTS if (comboBoxReconnect.Text.Contains("Disable")) { Setting.Values.HotKeyReconnect = 0; @@ -965,7 +968,7 @@ namespace MouseWithoutBorders { Setting.Values.HotKeyReconnect = comboBoxReconnect.Text[0]; } - +#endif ShowUpdateMessage(); } @@ -1006,6 +1009,7 @@ namespace MouseWithoutBorders private void ComboBoxEasyMouse_TextChanged(object sender, EventArgs e) { +#if OBSOLETE_SHORTCUTS if (comboBoxEasyMouse.Text.Contains("Disable")) { Setting.Values.HotKeyToggleEasyMouse = 0; @@ -1014,7 +1018,7 @@ namespace MouseWithoutBorders { Setting.Values.HotKeyToggleEasyMouse = comboBoxEasyMouse.Text[0]; } - +#endif ShowUpdateMessage(); } diff --git a/src/settings-ui/Settings.UI.Library/MouseWithoutBordersProperties.cs b/src/settings-ui/Settings.UI.Library/MouseWithoutBordersProperties.cs index d15a573037..7ec3604562 100644 --- a/src/settings-ui/Settings.UI.Library/MouseWithoutBordersProperties.cs +++ b/src/settings-ui/Settings.UI.Library/MouseWithoutBordersProperties.cs @@ -23,6 +23,14 @@ namespace Microsoft.PowerToys.Settings.UI.Library public class MouseWithoutBordersProperties : ICloneable { + public static HotkeySettings DefaultHotKeySwitch2AllPC => new HotkeySettings(); + + public static HotkeySettings DefaultHotKeyLockMachine => new HotkeySettings(true, true, true, false, 0x4C); + + public static HotkeySettings DefaultHotKeyReconnect => new HotkeySettings(true, true, true, false, 0x52); + + public static HotkeySettings DefaultHotKeyToggleEasyMouse => new HotkeySettings(true, true, true, false, 0x45); + public StringProperty SecurityKey { get; set; } [JsonConverter(typeof(BoolPropertyJsonConverter))] @@ -86,14 +94,30 @@ namespace Microsoft.PowerToys.Settings.UI.Library public IntProperty HotKeySwitchMachine { get; set; } + [ObsoleteAttribute("Use ToggleEasyMouseShortcut instead", false)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public IntProperty HotKeyToggleEasyMouse { get; set; } + [ObsoleteAttribute("Use LockMachineShortcut instead", false)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public IntProperty HotKeyLockMachine { get; set; } + [ObsoleteAttribute("Use ReconnectShortcut instead", false)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public IntProperty HotKeyReconnect { get; set; } + [ObsoleteAttribute("Use Switch2AllPCShortcut instead", false)] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public IntProperty HotKeySwitch2AllPC { get; set; } + public HotkeySettings ToggleEasyMouseShortcut { get; set; } + + public HotkeySettings LockMachineShortcut { get; set; } + + public HotkeySettings ReconnectShortcut { get; set; } + + public HotkeySettings Switch2AllPCShortcut { get; set; } + public IntProperty TCPPort { get; set; } [JsonConverter(typeof(BoolPropertyJsonConverter))] @@ -127,10 +151,10 @@ namespace Microsoft.PowerToys.Settings.UI.Library UseService = false; HotKeySwitchMachine = new IntProperty(0x70); // VK.F1 - HotKeyToggleEasyMouse = new IntProperty(0x45); // VK.E - HotKeyLockMachine = new IntProperty(0x4C); // VK.L - HotKeyReconnect = new IntProperty(0x52); // VK.R - HotKeySwitch2AllPC = new IntProperty(0); // Disabled + ToggleEasyMouseShortcut = DefaultHotKeyToggleEasyMouse; + LockMachineShortcut = DefaultHotKeyLockMachine; + ReconnectShortcut = DefaultHotKeyReconnect; + Switch2AllPCShortcut = DefaultHotKeySwitch2AllPC; // These are internal, i.e. cannot be edited directly from UI MachinePool = ":,:,:,:"; diff --git a/src/settings-ui/Settings.UI.Library/MouseWithoutBordersSettings.cs b/src/settings-ui/Settings.UI.Library/MouseWithoutBordersSettings.cs index 35b831e9be..40038cd314 100644 --- a/src/settings-ui/Settings.UI.Library/MouseWithoutBordersSettings.cs +++ b/src/settings-ui/Settings.UI.Library/MouseWithoutBordersSettings.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Diagnostics; using System.Text.Json; using System.Text.Json.Serialization; using Microsoft.PowerToys.Settings.UI.Library.Interfaces; @@ -20,7 +21,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library { Name = ModuleName; Properties = new MouseWithoutBordersProperties(); - Version = "1.0"; + Version = "1.1"; } public string GetModuleName() @@ -28,10 +29,51 @@ namespace Microsoft.PowerToys.Settings.UI.Library return Name; } + public HotkeySettings ConvertMouseWithoutBordersHotKeyToPowerToys(int value) + { + // VK_A <= value <= VK_Z + if (value >= 0x41 && value <= 0x5A) + { + return new HotkeySettings(false, true, true, false, value); + } + else + { + // Disabled state + return new HotkeySettings(false, false, false, false, 0); + } + } + // This can be utilized in the future if the settings.json file is to be modified/deleted. public bool UpgradeSettingsConfiguration() { +#pragma warning disable CS0618 // We use obsolete members to upgrade them + bool downgradedThenUpgraded = Version != "1.0" && (Properties.HotKeyToggleEasyMouse != null || + Properties.HotKeyLockMachine != null || + Properties.HotKeyReconnect != null || + Properties.HotKeySwitch2AllPC != null); + + if (Version == "1.0" || downgradedThenUpgraded) + { + Version = "1.1"; + + Properties.ToggleEasyMouseShortcut = ConvertMouseWithoutBordersHotKeyToPowerToys(Properties.HotKeyToggleEasyMouse.Value); + + Properties.LockMachineShortcut = ConvertMouseWithoutBordersHotKeyToPowerToys(Properties.HotKeyLockMachine.Value); + + Properties.ReconnectShortcut = ConvertMouseWithoutBordersHotKeyToPowerToys(Properties.HotKeyReconnect.Value); + + Properties.Switch2AllPCShortcut = ConvertMouseWithoutBordersHotKeyToPowerToys(Properties.HotKeySwitch2AllPC.Value); + + Properties.HotKeyToggleEasyMouse = null; + Properties.HotKeyLockMachine = null; + Properties.HotKeyReconnect = null; + Properties.HotKeySwitch2AllPC = null; + + return true; + } + return false; +#pragma warning restore CS0618 } public virtual void Save(ISettingsUtils settingsUtils) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutControl.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutControl.xaml.cs index 0b77571eda..50f0fb4f87 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutControl.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutControl.xaml.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using CommunityToolkit.WinUI.UI; using Microsoft.PowerToys.Settings.UI.Helpers; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.UI.Xaml; @@ -33,9 +34,39 @@ namespace Microsoft.PowerToys.Settings.UI.Controls public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register("Enabled", typeof(bool), typeof(ShortcutControl), null); public static readonly DependencyProperty HotkeySettingsProperty = DependencyProperty.Register("HotkeySettings", typeof(HotkeySettings), typeof(ShortcutControl), null); + public static readonly DependencyProperty AllowDisableProperty = DependencyProperty.Register("AllowDisable", typeof(bool), typeof(ShortcutControl), new PropertyMetadata(false, OnAllowDisableChanged)); + + private static void OnAllowDisableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var me = d as ShortcutControl; + if (me == null) + { + return; + } + + var description = me.c?.FindDescendant(); + if (description == null) + { + return; + } + + var resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader; + + var newValue = (bool)(e?.NewValue ?? false); + + var text = newValue ? resourceLoader.GetString("Activation_Shortcut_With_Disable_Description") : resourceLoader.GetString("Activation_Shortcut_Description"); + description.Text = text; + } + private ShortcutDialogContentControl c = new ShortcutDialogContentControl(); private ContentDialog shortcutDialog; + public bool AllowDisable + { + get => (bool)GetValue(AllowDisableProperty); + set => SetValue(AllowDisableProperty, value); + } + public bool Enabled { get @@ -106,9 +137,12 @@ namespace Microsoft.PowerToys.Settings.UI.Controls }; shortcutDialog.PrimaryButtonClick += ShortcutDialog_PrimaryButtonClick; shortcutDialog.SecondaryButtonClick += ShortcutDialog_Reset; + shortcutDialog.RightTapped += ShortcutDialog_Disable; shortcutDialog.Opened += ShortcutDialog_Opened; shortcutDialog.Closing += ShortcutDialog_Closing; AutomationProperties.SetName(EditButton, resourceLoader.GetString("Activation_Shortcut_Title")); + + OnAllowDisableChanged(this, null); } private void ShortcutControl_Unloaded(object sender, RoutedEventArgs e) @@ -381,6 +415,21 @@ namespace Microsoft.PowerToys.Settings.UI.Controls shortcutDialog.Hide(); } + private void ShortcutDialog_Disable(object sender, RightTappedRoutedEventArgs e) + { + if (!AllowDisable) + { + return; + } + + var empty = new HotkeySettings(); + HotkeySettings = empty; + + PreviewKeysControl.ItemsSource = HotkeySettings.GetKeysList(); + AutomationProperties.SetHelpText(EditButton, HotkeySettings.ToString()); + shortcutDialog.Hide(); + } + private static bool ComboIsValid(HotkeySettings settings) { if (settings != null && (settings.IsValid() || settings.IsEmpty())) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutDialogContentControl.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutDialogContentControl.xaml index 0429f5dae4..9472c661cc 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutDialogContentControl.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ShortcutControl/ShortcutDialogContentControl.xaml @@ -18,7 +18,6 @@ - - - - A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - + + + - - - - A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - + + + - - - - A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - - - - - - - A - B - C - D - E - F - G - H - I - J - K - L - M - N - O - P - Q - R - S - T - U - V - W - X - Y - Z - + + + + + + + + diff --git a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw index b6b5521878..6504597a5a 100644 --- a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw +++ b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw @@ -420,8 +420,14 @@ Shift This is the Shift keyboard key + + Shortcut to lock all machines. + + + Hit this hotkey twice to lock all machines. Note: Only the machines which have the same shortcut configured will be locked. + - Shortcut to toggle Easy Mouse. Ctrl+Alt+: + Shortcut to toggle Easy Mouse. Ctrl and Alt are the keyboard keys @@ -449,35 +455,23 @@ Disabled - - Shortcut to press twice quickly to lock all machines. Ctrl+Alt+: - Ctrl and Alt are the keyboard keys - - - Click on Ctrl+Alt+ the chosen option twice quickly to lock all machines. Note: Only the machines which have the same shortcut configured will be locked. - Ctrl and Alt are the keyboard keys - Disabled - Shortcut to try reconnecting. Ctrl+Alt+: - Ctrl and Alt are the keyboard keys + Shortcut to try reconnecting - Click on Ctrl+Alt+ the chosen option to reconnect. - Ctrl and Alt are the keyboard keys + Just in case the connection is lost for any reason. Disabled - Shortcut to switch to multiple machine mode. Ctrl+Alt+: - Ctrl and Alt are the keyboard keys + Shortcut to switch to multiple machine mode. - Allows controlling all computers at once. Pressing Ctrl three times is also an option. - This is the Ctrl keyboard key + Allows controlling all computers at once. Disabled @@ -2471,8 +2465,12 @@ From there, simply click on one of the supported files in the File Explorer and Cancel - - Press a combination of keys to change this shortcut + + Press a combination of keys to change this shortcut + + + Press a combination of keys to change this shortcut. +Right-click to remove the key combination, thereby deactivating the shortcut. Reset diff --git a/src/settings-ui/Settings.UI/ViewModels/MouseWithoutBordersViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/MouseWithoutBordersViewModel.cs index 6d83802c15..5a9d499055 100644 --- a/src/settings-ui/Settings.UI/ViewModels/MouseWithoutBordersViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/MouseWithoutBordersViewModel.cs @@ -276,7 +276,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels } catch (Exception ex) { - Logger.LogError($"Couldn't create SettingsSync: {ex}"); + if (IsEnabled) + { + Logger.LogError($"Couldn't create SettingsSync: {ex}"); + } + return null; } } @@ -475,10 +479,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels /* TODO: Error handling */ _selectedSwitchBetweenMachineShortcutOptionsIndex = Array.IndexOf(_switchBetweenMachineShortcutOptions, moduleSettings.Properties.HotKeySwitchMachine.Value); _easyMouseOptionIndex = (EasyMouseOption)moduleSettings.Properties.EasyMouse.Value; - _toggleEasyMouseShortcutIndex = ConvertMouseWithoutBordersHotKeyValueToIndex(moduleSettings.Properties.HotKeyToggleEasyMouse.Value); - _lockMachinesShortcutIndex = ConvertMouseWithoutBordersHotKeyValueToIndex(moduleSettings.Properties.HotKeyLockMachine.Value); - _reconnectShortcutIndex = ConvertMouseWithoutBordersHotKeyValueToIndex(moduleSettings.Properties.HotKeyReconnect.Value); - _switch2AllPcShortcutIndex = ConvertMouseWithoutBordersHotKeyValueToIndex(moduleSettings.Properties.HotKeySwitch2AllPC.Value, 1); + LoadMachineMatrixString(); } @@ -822,111 +823,60 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels } } - public int ConvertMouseWithoutBordersHotKeyValueToIndex(int value, int additionalOptions = 0) + public HotkeySettings ToggleEasyMouseShortcut { - if (value >= 0x41 && value <= 0x5A) - { - return value - 0x40 + additionalOptions; /* VK_A <= value <= VK_Z */ - } - - if (value <= additionalOptions) - { - return value; - } - - return 0; /* Disabled */ - } - - public int ConvertMouseWithoutBordersHotKeyIndexToValue(int index, int additionalOptions = 0) - { - if (index >= additionalOptions + 1 && index <= additionalOptions + 26) - { - return index + 0x40 - additionalOptions; /* VK_A to VK_Z */ - } - - if (index <= additionalOptions) - { - return index; - } - - return 0; /* Disabled */ - } - - private int _toggleEasyMouseShortcutIndex; - - public int ToggleEasyMouseShortcutIndex - { - get - { - return _toggleEasyMouseShortcutIndex; - } + get => Settings.Properties.ToggleEasyMouseShortcut; set { - if (_toggleEasyMouseShortcutIndex != value) + if (Settings.Properties.ToggleEasyMouseShortcut != value) { - _toggleEasyMouseShortcutIndex = value; - Settings.Properties.HotKeyToggleEasyMouse.Value = ConvertMouseWithoutBordersHotKeyIndexToValue(value); + Settings.Properties.ToggleEasyMouseShortcut = value ?? MouseWithoutBordersProperties.DefaultHotKeyToggleEasyMouse; NotifyPropertyChanged(); } } } - private int _lockMachinesShortcutIndex; - - public int LockMachinesShortcutIndex + public HotkeySettings LockMachinesShortcut { - get - { - return _lockMachinesShortcutIndex; - } + get => Settings.Properties.LockMachineShortcut; set { - if (_lockMachinesShortcutIndex != value) + if (Settings.Properties.LockMachineShortcut != value) { - _lockMachinesShortcutIndex = value; - Settings.Properties.HotKeyLockMachine.Value = ConvertMouseWithoutBordersHotKeyIndexToValue(value); + Settings.Properties.LockMachineShortcut = value; + Settings.Properties.LockMachineShortcut = value ?? MouseWithoutBordersProperties.DefaultHotKeyLockMachine; NotifyPropertyChanged(); } } } - private int _reconnectShortcutIndex; - - public int ReconnectShortcutIndex + public HotkeySettings ReconnectShortcut { - get - { - return _reconnectShortcutIndex; - } + get => Settings.Properties.ReconnectShortcut; set { - if (_reconnectShortcutIndex != value) + if (Settings.Properties.ReconnectShortcut != value) { - _reconnectShortcutIndex = value; - Settings.Properties.HotKeyReconnect.Value = ConvertMouseWithoutBordersHotKeyIndexToValue(value); + Settings.Properties.ReconnectShortcut = value; + Settings.Properties.ReconnectShortcut = value ?? MouseWithoutBordersProperties.DefaultHotKeyReconnect; NotifyPropertyChanged(); } } } - private int _switch2AllPcShortcutIndex; - - public int Switch2AllPcShortcutIndex + public HotkeySettings HotKeySwitch2AllPC { - get - { - return _switch2AllPcShortcutIndex; - } + get => Settings.Properties.Switch2AllPCShortcut; set { - if (_switch2AllPcShortcutIndex != value) + if (Settings.Properties.Switch2AllPCShortcut != value) { - _switch2AllPcShortcutIndex = value; - Settings.Properties.HotKeySwitch2AllPC.Value = ConvertMouseWithoutBordersHotKeyIndexToValue(value, 1); + Settings.Properties.Switch2AllPCShortcut = value; + Settings.Properties.Switch2AllPCShortcut = value ?? MouseWithoutBordersProperties.DefaultHotKeySwitch2AllPC; NotifyPropertyChanged(); } }