mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 19:57:57 +01:00
Fix ctrl alt key in Keyboard Hook and Advanced Paste custom actions
This commit is contained in:
@@ -21,6 +21,11 @@ namespace RunnerV2.Helpers
|
|||||||
|
|
||||||
private static void OnKeyDown(int key)
|
private static void OnKeyDown(int key)
|
||||||
{
|
{
|
||||||
|
if ((VirtualKey)key == VirtualKey.RightMenu && _ctrlState)
|
||||||
|
{
|
||||||
|
_ctrlAltState = true;
|
||||||
|
}
|
||||||
|
|
||||||
switch ((VirtualKey)key)
|
switch ((VirtualKey)key)
|
||||||
{
|
{
|
||||||
case VirtualKey.Control:
|
case VirtualKey.Control:
|
||||||
@@ -41,6 +46,20 @@ namespace RunnerV2.Helpers
|
|||||||
case VirtualKey.LeftWindows:
|
case VirtualKey.LeftWindows:
|
||||||
case VirtualKey.RightWindows:
|
case VirtualKey.RightWindows:
|
||||||
_winState = true;
|
_winState = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (OnKeyboardEvent(new HotkeySettings
|
||||||
|
{
|
||||||
|
Code = key,
|
||||||
|
Ctrl = _ctrlState,
|
||||||
|
Alt = _altState,
|
||||||
|
Shift = _shiftState,
|
||||||
|
Win = _winState,
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,16 +89,15 @@ namespace RunnerV2.Helpers
|
|||||||
case VirtualKey.RightWindows:
|
case VirtualKey.RightWindows:
|
||||||
_winState = false;
|
_winState = false;
|
||||||
break;
|
break;
|
||||||
default:
|
}
|
||||||
OnKeyboardEvent(new HotkeySettings
|
|
||||||
|
// Correctly release Ctrl key if Ctrl+Alt (AltGr) was used.
|
||||||
|
if (_ctrlAltState && (VirtualKey)key == VirtualKey.RightMenu)
|
||||||
{
|
{
|
||||||
Code = key,
|
_ctrlAltState = false;
|
||||||
Ctrl = _ctrlState,
|
_ctrlState = false;
|
||||||
Alt = _altState,
|
|
||||||
Shift = _shiftState,
|
SendSingleKeyboardInput((short)VirtualKey.LeftControl, (uint)NativeKeyboardHelper.KeyEventF.KeyUp);
|
||||||
Win = _winState,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SendSingleKeyboardInput((short)key, (uint)NativeKeyboardHelper.KeyEventF.KeyUp);
|
SendSingleKeyboardInput((short)key, (uint)NativeKeyboardHelper.KeyEventF.KeyUp);
|
||||||
@@ -89,6 +107,7 @@ namespace RunnerV2.Helpers
|
|||||||
private static bool _altState;
|
private static bool _altState;
|
||||||
private static bool _shiftState;
|
private static bool _shiftState;
|
||||||
private static bool _winState;
|
private static bool _winState;
|
||||||
|
private static bool _ctrlAltState;
|
||||||
|
|
||||||
private static bool _isActive;
|
private static bool _isActive;
|
||||||
|
|
||||||
@@ -114,8 +133,10 @@ namespace RunnerV2.Helpers
|
|||||||
_keyboardHooks.Remove(moduleName);
|
_keyboardHooks.Remove(moduleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnKeyboardEvent(HotkeySettings pressedHotkey)
|
private static bool OnKeyboardEvent(HotkeySettings pressedHotkey)
|
||||||
{
|
{
|
||||||
|
bool shortcutHandled = false;
|
||||||
|
|
||||||
foreach (var moduleHooks in _keyboardHooks.Values)
|
foreach (var moduleHooks in _keyboardHooks.Values)
|
||||||
{
|
{
|
||||||
foreach (var (hotkeySettings, action) in moduleHooks)
|
foreach (var (hotkeySettings, action) in moduleHooks)
|
||||||
@@ -123,9 +144,12 @@ namespace RunnerV2.Helpers
|
|||||||
if (hotkeySettings == pressedHotkey)
|
if (hotkeySettings == pressedHotkey)
|
||||||
{
|
{
|
||||||
action();
|
action();
|
||||||
|
shortcutHandled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return shortcutHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Start()
|
public static void Start()
|
||||||
@@ -147,7 +171,12 @@ namespace RunnerV2.Helpers
|
|||||||
// Function to send a single key event to the system which would be ignored by the hotkey control.
|
// Function to send a single key event to the system which would be ignored by the hotkey control.
|
||||||
private static void SendSingleKeyboardInput(short keyCode, uint keyStatus)
|
private static void SendSingleKeyboardInput(short keyCode, uint keyStatus)
|
||||||
{
|
{
|
||||||
NativeKeyboardHelper.INPUT inputShift = new()
|
if (IsExtendedVirtualKey(keyCode))
|
||||||
|
{
|
||||||
|
keyStatus |= (uint)NativeKeyboardHelper.KeyEventF.ExtendedKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeKeyboardHelper.INPUT input = new()
|
||||||
{
|
{
|
||||||
type = NativeKeyboardHelper.INPUTTYPE.INPUT_KEYBOARD,
|
type = NativeKeyboardHelper.INPUTTYPE.INPUT_KEYBOARD,
|
||||||
data = new NativeKeyboardHelper.InputUnion
|
data = new NativeKeyboardHelper.InputUnion
|
||||||
@@ -161,9 +190,30 @@ namespace RunnerV2.Helpers
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
NativeKeyboardHelper.INPUT[] inputs = [inputShift];
|
NativeKeyboardHelper.INPUT[] inputs = [input];
|
||||||
|
|
||||||
_ = NativeMethods.SendInput(1, inputs, NativeKeyboardHelper.INPUT.Size);
|
_ = NativeMethods.SendInput(1, inputs, NativeKeyboardHelper.INPUT.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsExtendedVirtualKey(short vk)
|
||||||
|
{
|
||||||
|
return vk switch
|
||||||
|
{
|
||||||
|
0xA5 => true, // VK_RMENU (Right Alt - AltGr)
|
||||||
|
0xA3 => true, // VK_RCONTROL
|
||||||
|
0x2D => true, // VK_INSERT
|
||||||
|
0x2E => true, // VK_DELETE
|
||||||
|
0x23 => true, // VK_END
|
||||||
|
0x24 => true, // VK_HOME
|
||||||
|
0x21 => true, // VK_PRIOR (Page Up)
|
||||||
|
0x22 => true, // VK_NEXT (Page Down)
|
||||||
|
0x25 => true, // VK_LEFT
|
||||||
|
0x26 => true, // VK_UP
|
||||||
|
0x27 => true, // VK_RIGHT
|
||||||
|
0x28 => true, // VK_DOWN
|
||||||
|
0x90 => true, // VK_NUMLOCK
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using ManagedCommon;
|
|
||||||
using Microsoft.PowerToys.Settings.UI.Library;
|
using Microsoft.PowerToys.Settings.UI.Library;
|
||||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||||
using PowerToys.GPOWrapper;
|
using PowerToys.GPOWrapper;
|
||||||
@@ -64,18 +64,21 @@ namespace RunnerV2.ModuleInterfaces
|
|||||||
Process.Start("WinUI3Apps\\PowerToys.AdvancedPaste.exe", $"{Environment.ProcessId} {ipcName}");
|
Process.Start("WinUI3Apps\\PowerToys.AdvancedPaste.exe", $"{Environment.ProcessId} {ipcName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnSettingsChanged()
|
public void OnSettingsChanged(string settingsKind, JsonElement jsonProperties)
|
||||||
{
|
{
|
||||||
PopulateShortcuts();
|
PopulateShortcuts();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PopulateShortcuts()
|
public void PopulateShortcuts()
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(_ipc);
|
if (_ipc is null)
|
||||||
|
{
|
||||||
|
_ipc = new TwoWayPipeMessageIPCManaged(string.Empty, @"\\.\pipe\PowerToys.AdvancedPaste", (_) => { });
|
||||||
|
}
|
||||||
|
|
||||||
Shortcuts.Clear();
|
Shortcuts.Clear();
|
||||||
|
|
||||||
AdvancedPasteSettings settings = new SettingsUtils().GetSettings<AdvancedPasteSettings>();
|
AdvancedPasteSettings settings = new SettingsUtils().GetSettingsOrDefault<AdvancedPasteSettings>(Name);
|
||||||
Shortcuts.Add((settings.Properties.AdvancedPasteUIShortcut, () =>
|
Shortcuts.Add((settings.Properties.AdvancedPasteUIShortcut, () =>
|
||||||
_ipc.Send("ShowUI")
|
_ipc.Send("ShowUI")
|
||||||
));
|
));
|
||||||
@@ -84,10 +87,17 @@ namespace RunnerV2.ModuleInterfaces
|
|||||||
Shortcuts.Add((settings.Properties.PasteAsJsonShortcut, () => _ipc.Send("PasteJson")));
|
Shortcuts.Add((settings.Properties.PasteAsJsonShortcut, () => _ipc.Send("PasteJson")));
|
||||||
|
|
||||||
HotkeyAccessor[] hotkeyAccessors = settings.GetAllHotkeyAccessors();
|
HotkeyAccessor[] hotkeyAccessors = settings.GetAllHotkeyAccessors();
|
||||||
for (int i = 4; i < hotkeyAccessors.Length; i++)
|
int additionalActionsCount = settings.Properties.AdditionalActions.GetAllActions().Count() - 2;
|
||||||
|
for (int i = 0; i < additionalActionsCount; i++)
|
||||||
{
|
{
|
||||||
HotkeyAccessor hotkeyAccessor = hotkeyAccessors[i];
|
int scopedI = i;
|
||||||
Shortcuts.Add((hotkeyAccessor.Value, () => _ipc.Send($"CustomPaste {i}")));
|
Shortcuts.Add((hotkeyAccessors[4 + i].Value, () => _ipc.Send("AdditionalAction " + (3 + scopedI))));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 4 + additionalActionsCount; i < hotkeyAccessors.Length; i++)
|
||||||
|
{
|
||||||
|
int scopedI = i;
|
||||||
|
Shortcuts.Add((hotkeyAccessors[i].Value, () => _ipc.Send("CustomAction " + (scopedI - 5 - additionalActionsCount))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ using Microsoft.UI.Windowing;
|
|||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using PowerToys.Interop;
|
using PowerToys.Interop;
|
||||||
using Windows.Graphics;
|
using Windows.Graphics;
|
||||||
|
using WinRT;
|
||||||
using WinUIEx;
|
using WinUIEx;
|
||||||
|
|
||||||
using static AdvancedPaste.Helpers.NativeMethods;
|
using static AdvancedPaste.Helpers.NativeMethods;
|
||||||
@@ -44,13 +45,6 @@ namespace AdvancedPaste
|
|||||||
|
|
||||||
public ETWTrace EtwTrace { get; private set; } = new ETWTrace();
|
public ETWTrace EtwTrace { get; private set; } = new ETWTrace();
|
||||||
|
|
||||||
private static readonly Dictionary<string, PasteFormats> AdditionalActionIPCKeys =
|
|
||||||
typeof(PasteFormats).GetFields()
|
|
||||||
.Where(field => field.IsLiteral)
|
|
||||||
.Select(field => (Format: (PasteFormats)field.GetRawConstantValue(), field.GetCustomAttribute<PasteFormatMetadataAttribute>().IPCKey))
|
|
||||||
.Where(field => field.IPCKey != null)
|
|
||||||
.ToDictionary(field => field.IPCKey, field => field.Format);
|
|
||||||
|
|
||||||
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||||
private readonly OptionsViewModel viewModel;
|
private readonly OptionsViewModel viewModel;
|
||||||
|
|
||||||
@@ -187,14 +181,14 @@ namespace AdvancedPaste
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!AdditionalActionIPCKeys.TryGetValue(messageParts[1], out PasteFormats pasteFormat))
|
if (!int.TryParse(messageParts[1], CultureInfo.InvariantCulture, out int customActionId))
|
||||||
{
|
{
|
||||||
Logger.LogWarning($"Unexpected additional action type {messageParts[1]}");
|
Logger.LogWarning($"Unexpected additional action type {messageParts[1]}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await ShowWindow();
|
await ShowWindow();
|
||||||
await viewModel.ExecutePasteFormatAsync(pasteFormat, PasteActionSource.GlobalKeyboardShortcut);
|
await viewModel.ExecutePasteFormatAsync((PasteFormats)customActionId, PasteActionSource.GlobalKeyboardShortcut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user