Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Fixed an issue where it didn't work to map certain keys to Actions #15420

Merged
merged 25 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1c1e746
Fix: Problem with mapping certain keys in action section
XTorLukas May 16, 2024
c33864f
Merge branch 'main' into xtorlukas/Fix-HotKeyCharCorrect
XTorLukas May 17, 2024
3290b06
Using suggestions: Fix formatting
XTorLukas May 17, 2024
86673f7
Adding NumPad Keys correct mapping
XTorLukas May 17, 2024
9c80642
Code Quality: Create better Parser for string with start '+' e.g.: '+…
XTorLukas May 17, 2024
dcd4776
Code Quality: Adding invalid keys filter & code optimization
XTorLukas May 17, 2024
97f2fcd
Fix: Remove the dead key problem
XTorLukas May 17, 2024
18c16fd
Fix: Incorrect definition of method
XTorLukas May 17, 2024
7781c3f
Fix: Buffer size was incorrect
XTorLukas May 18, 2024
729c424
Fix: There are never been dead key, no need here
XTorLukas May 18, 2024
3d41aee
Code Quality: Add `InvalidKeyTeachingTip`
XTorLukas May 18, 2024
4b3be28
Fix: Correct `InvalidKeyTeachingTip` position open
XTorLukas May 18, 2024
ee6ebe4
Code Quality: Optimized key handling logic and improved code readabil…
XTorLukas May 18, 2024
7dc7e1e
Code quality: Update parser and change NumPad key representation
XTorLukas May 19, 2024
36c13ea
Fix: Key binding alignment
XTorLukas May 19, 2024
d0dad4c
Fix: Added compatibility with Russian characters
XTorLukas May 19, 2024
d631154
Merge branch 'main' into xtorlukas/Fix-HotKeyCharCorrect
XTorLukas May 20, 2024
cb7c282
Update Resources file
XTorLukas May 20, 2024
1c78764
Merge branch 'xtorlukas/Fix-HotKeyCharCorrect' of https://github.com/…
XTorLukas May 20, 2024
31de204
Merge branch 'main' into xtorlukas/Fix-HotKeyCharCorrect
yaira2 May 21, 2024
6e07d09
Merge branch 'xtorlukas/Fix-HotKeyCharCorrect' of https://github.com/…
XTorLukas May 21, 2024
30b0937
Update src/Files.App/Strings/en-US/Resources.resw
yaira2 May 21, 2024
16e9a11
Update src/Files.App/UserControls/KeyboardShortcut/KeyboardShortcut.xaml
XTorLukas May 23, 2024
3907527
Update: src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs
XTorLukas May 23, 2024
d015e04
Merge branch 'xtorlukas/Fix-HotKeyCharCorrect' of https://github.com/…
XTorLukas May 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 110 additions & 57 deletions src/Files.App/Data/Commands/HotKey/HotKey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,60 +81,46 @@ namespace Files.App.Data.Commands
[Keys.Number7] = "7",
[Keys.Number8] = "8",
[Keys.Number9] = "9",
[Keys.Pad0] = GetLocalizedKey("Pad0"),
[Keys.Pad1] = GetLocalizedKey("Pad1"),
[Keys.Pad2] = GetLocalizedKey("Pad2"),
[Keys.Pad3] = GetLocalizedKey("Pad3"),
[Keys.Pad4] = GetLocalizedKey("Pad4"),
[Keys.Pad5] = GetLocalizedKey("Pad5"),
[Keys.Pad6] = GetLocalizedKey("Pad6"),
[Keys.Pad7] = GetLocalizedKey("Pad7"),
[Keys.Pad8] = GetLocalizedKey("Pad8"),
[Keys.Pad9] = GetLocalizedKey("Pad9"),
[Keys.A] = "A",
[Keys.B] = "B",
[Keys.C] = "C",
[Keys.D] = "D",
[Keys.E] = "E",
[Keys.F] = "F",
[Keys.G] = "G",
[Keys.H] = "H",
[Keys.I] = "I",
[Keys.J] = "J",
[Keys.K] = "K",
[Keys.L] = "L",
[Keys.M] = "M",
[Keys.N] = "N",
[Keys.O] = "O",
[Keys.P] = "P",
[Keys.Q] = "Q",
[Keys.R] = "R",
[Keys.S] = "S",
[Keys.T] = "T",
[Keys.U] = "U",
[Keys.V] = "V",
[Keys.W] = "W",
[Keys.X] = "X",
[Keys.Y] = "Y",
[Keys.Z] = "Z",
[Keys.Add] = "+",
[Keys.Subtract] = "-",
[Keys.Multiply] = "*",
[Keys.Divide] = "/",
[Keys.Oem1] = GetKeyCharacter(Forms.Keys.Oem1),
[Keys.Oem2] = GetKeyCharacter(Forms.Keys.Oem2),
[Keys.Oem3] = GetKeyCharacter(Forms.Keys.Oem3),
[Keys.Oem4] = GetKeyCharacter(Forms.Keys.Oem4),
[Keys.Oem5] = GetKeyCharacter(Forms.Keys.Oem5),
[Keys.Oem6] = GetKeyCharacter(Forms.Keys.Oem6),
[Keys.Oem7] = GetKeyCharacter(Forms.Keys.Oem7),
[Keys.Oem8] = GetKeyCharacter(Forms.Keys.Oem8),
[Keys.OemPlus] = GetKeyCharacter(Forms.Keys.Oemplus),
[Keys.OemComma] = GetKeyCharacter(Forms.Keys.Oemcomma),
[Keys.OemMinus] = GetKeyCharacter(Forms.Keys.OemMinus),
[Keys.OemPeriod] = GetKeyCharacter(Forms.Keys.OemPeriod),
[Keys.Oem102] = GetKeyCharacter(Forms.Keys.Oem102),
[Keys.OemClear] = GetKeyCharacter(Forms.Keys.OemClear),
[Keys.A] = GetKeyCharacter(Forms.Keys.A).ToUpper(),
[Keys.B] = GetKeyCharacter(Forms.Keys.B).ToUpper(),
[Keys.C] = GetKeyCharacter(Forms.Keys.C).ToUpper(),
[Keys.D] = GetKeyCharacter(Forms.Keys.D).ToUpper(),
[Keys.E] = GetKeyCharacter(Forms.Keys.E).ToUpper(),
[Keys.F] = GetKeyCharacter(Forms.Keys.F).ToUpper(),
[Keys.G] = GetKeyCharacter(Forms.Keys.G).ToUpper(),
[Keys.H] = GetKeyCharacter(Forms.Keys.H).ToUpper(),
[Keys.I] = GetKeyCharacter(Forms.Keys.I).ToUpper(),
[Keys.J] = GetKeyCharacter(Forms.Keys.J).ToUpper(),
[Keys.K] = GetKeyCharacter(Forms.Keys.K).ToUpper(),
[Keys.L] = GetKeyCharacter(Forms.Keys.L).ToUpper(),
[Keys.M] = GetKeyCharacter(Forms.Keys.M).ToUpper(),
[Keys.N] = GetKeyCharacter(Forms.Keys.N).ToUpper(),
[Keys.O] = GetKeyCharacter(Forms.Keys.O).ToUpper(),
[Keys.P] = GetKeyCharacter(Forms.Keys.P).ToUpper(),
[Keys.Q] = GetKeyCharacter(Forms.Keys.Q).ToUpper(),
[Keys.R] = GetKeyCharacter(Forms.Keys.R).ToUpper(),
[Keys.S] = GetKeyCharacter(Forms.Keys.S).ToUpper(),
[Keys.T] = GetKeyCharacter(Forms.Keys.T).ToUpper(),
[Keys.U] = GetKeyCharacter(Forms.Keys.U).ToUpper(),
[Keys.V] = GetKeyCharacter(Forms.Keys.V).ToUpper(),
[Keys.W] = GetKeyCharacter(Forms.Keys.W).ToUpper(),
[Keys.X] = GetKeyCharacter(Forms.Keys.X).ToUpper(),
[Keys.Y] = GetKeyCharacter(Forms.Keys.Y).ToUpper(),
[Keys.Z] = GetKeyCharacter(Forms.Keys.Z).ToUpper(),
[Keys.Oem1] = GetKeyCharacter(Forms.Keys.Oem1).ToUpper(),
[Keys.Oem2] = GetKeyCharacter(Forms.Keys.Oem2).ToUpper(),
[Keys.Oem3] = GetKeyCharacter(Forms.Keys.Oem3).ToUpper(),
[Keys.Oem4] = GetKeyCharacter(Forms.Keys.Oem4).ToUpper(),
[Keys.Oem5] = GetKeyCharacter(Forms.Keys.Oem5).ToUpper(),
[Keys.Oem6] = GetKeyCharacter(Forms.Keys.Oem6).ToUpper(),
[Keys.Oem7] = GetKeyCharacter(Forms.Keys.Oem7).ToUpper(),
[Keys.Oem8] = GetKeyCharacter(Forms.Keys.Oem8).ToUpper(),
[Keys.Oem102] = GetKeyCharacter(Forms.Keys.Oem102).ToUpper(),
[Keys.OemPlus] = GetKeyCharacter(Forms.Keys.Oemplus).ToUpper(),
[Keys.OemComma] = GetKeyCharacter(Forms.Keys.Oemcomma).ToUpper(),
[Keys.OemMinus] = GetKeyCharacter(Forms.Keys.OemMinus).ToUpper(),
[Keys.OemPeriod] = GetKeyCharacter(Forms.Keys.OemPeriod).ToUpper(),
[Keys.OemClear] = GetKeyCharacter(Forms.Keys.OemClear).ToUpper(),
[Keys.Application] = GetLocalizedKey("Application"),
[Keys.Application1] = GetLocalizedKey("Application1"),
[Keys.Application2] = GetLocalizedKey("Application2"),
Expand All @@ -154,6 +140,23 @@ namespace Files.App.Data.Commands
[Keys.Mute] = GetLocalizedKey("MediaMute"),
[Keys.VolumeDown] = GetLocalizedKey("MediaVolumeDown"),
[Keys.VolumeUp] = GetLocalizedKey("MediaVolumeUp"),

// NumPad Keys
[Keys.Add] = GetLocalizedNumPadKey("+"),
[Keys.Subtract] = GetLocalizedNumPadKey("-"),
[Keys.Multiply] = GetLocalizedNumPadKey("*"),
[Keys.Divide] = GetLocalizedNumPadKey("/"),
[Keys.Decimal] = GetLocalizedNumPadKey("."),
[Keys.Pad0] = GetLocalizedNumPadKey("0"),
[Keys.Pad1] = GetLocalizedNumPadKey("1"),
[Keys.Pad2] = GetLocalizedNumPadKey("2"),
[Keys.Pad3] = GetLocalizedNumPadKey("3"),
[Keys.Pad4] = GetLocalizedNumPadKey("4"),
[Keys.Pad5] = GetLocalizedNumPadKey("5"),
[Keys.Pad6] = GetLocalizedNumPadKey("6"),
[Keys.Pad7] = GetLocalizedNumPadKey("7"),
[Keys.Pad8] = GetLocalizedNumPadKey("8"),
[Keys.Pad9] = GetLocalizedNumPadKey("9"),
}.ToFrozenDictionary();

/// <summary>
Expand Down Expand Up @@ -278,9 +281,39 @@ public static HotKey Parse(string code, bool localized = true)
var key = Keys.None;
var modifier = KeyModifiers.None;
bool isVisible = true;
var splitCharacter = '+';

// Remove leading and trailing whitespace from the code string
code = code.Trim();
var parts = code.Split('+').Select(part => part.Trim());

// Split the code by "++" into a list of parts
List<string> parts = [.. code.Split(new string(splitCharacter, 2), StringSplitOptions.None)];

if (parts.Count == 2)
{
// If there are two parts after splitting by "++", split the first part by "+"
// and append the second part prefixed with a "+"
parts = [.. parts.First().Split(splitCharacter), splitCharacter + parts.Last()];
}
else
{
// Split the code by a single '+' and trim each part
parts = [.. code.Split(splitCharacter)];

// If the resulting list has two parts and one of them is empty, use the original code as the single element
if (parts.Count == 2 && (string.IsNullOrEmpty(parts.First()) || string.IsNullOrEmpty(parts.Last())))
{
parts = [code];
}
else if (parts.Count > 0 && string.IsNullOrEmpty(parts.Last()))
{
// If the last part is empty, remove it and add a "+" to the last non-empty part
parts.RemoveAt(parts.Count - 1);
parts[^1] += splitCharacter;
}
}

parts = [.. parts.Select(part => part.Trim())];

foreach (var part in parts)
{
Expand Down Expand Up @@ -330,11 +363,31 @@ private static string GetLocalizedKey(string key)
return $"Key/{key}".GetLocalizedResource();
}

private static string GetLocalizedNumPadKey(string key)
{
return "NumPadTypeName".GetLocalizedResource() + " " + key;
}

private static string GetKeyCharacter(Forms.Keys key)
{
var buffer = new StringBuilder(256);
var buffer = new StringBuilder(4);
var state = new byte[256];
_ = Win32PInvoke.ToUnicode((uint)key, 0, state, buffer, 256, 0);

// Get the current keyboard state
if (!Win32PInvoke.GetKeyboardState(state))
return buffer.ToString();

// Convert the key to its virtual key code
var virtualKey = (uint)key;

// Map the virtual key to a scan code
var scanCode = Win32PInvoke.MapVirtualKey(virtualKey, 0);

// Get the active keyboard layout
var keyboardLayout = Win32PInvoke.GetKeyboardLayout(0);

if (Win32PInvoke.ToUnicodeEx(virtualKey, scanCode, state, buffer, buffer.Capacity, 0, keyboardLayout) > 0)
return buffer[^1].ToString();

return buffer.ToString();
}
Expand Down
1 change: 1 addition & 0 deletions src/Files.App/Data/Commands/HotKey/Keys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ public enum Keys : ushort
Subtract = VirtualKey.Subtract,
Multiply = VirtualKey.Multiply,
Divide = VirtualKey.Divide,
Decimal = VirtualKey.Decimal,
Oem1 = 186,
Oem2 = 191,
Oem3 = 192,
Expand Down
7 changes: 7 additions & 0 deletions src/Files.App/Data/Items/ModifiableActionItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ public bool IsInEditMode
set => SetProperty(ref _IsInEditMode, value);
}

private bool _IsValidKeyBinding;
public bool IsValidKeyBinding
{
get => _IsValidKeyBinding;
set => SetProperty(ref _IsValidKeyBinding, value);
}

private bool _IsDefinedByDefault;
public bool IsDefinedByDefault
{
Expand Down
44 changes: 43 additions & 1 deletion src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ IntPtr dwNewLong
WindowLongFlags nIndex,
IntPtr dwNewLong
);

[DllImport("shell32.dll")]
public static extern IntPtr SHBrowseForFolder(
ref BROWSEINFO lpbi
Expand Down Expand Up @@ -231,6 +231,48 @@ IntPtr lpOverlapped
uint flags
);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int ToUnicodeEx(
uint virtualKeyCode,
uint scanCode,
byte[] keyboardState,
[Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder receivingBuffer,
int bufferSize,
uint flags,
IntPtr keyboardLayout
);

[DllImport("user32.dll")]
public static extern bool GetKeyboardState(
byte[] lpKeyState
);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetKeyboardLayout
(
uint idThread
);

[DllImport("user32.dll")]
public static extern uint MapVirtualKey(
uint code,
uint mapType
);

[DllImport("user32.dll")]
public static extern bool TranslateMessage(ref MSG lpMsg);

[StructLayout(LayoutKind.Sequential)]
public struct MSG
XTorLukas marked this conversation as resolved.
Show resolved Hide resolved
{
public IntPtr hwnd;
public uint message;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public System.Drawing.Point pt;
}

[DllImport("api-ms-win-core-file-fromapp-l1-1-0.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern IntPtr CreateFileFromApp(
string lpFileName,
Expand Down
6 changes: 6 additions & 0 deletions src/Files.App/Strings/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -3736,6 +3736,9 @@
<data name="KeybindingAlreadyUsedNotification" xml:space="preserve">
<value>This key binding is already being used, please choose a different key binding to continue.</value>
</data>
<data name="KeybindingInvalidKeyNotification" xml:space="preserve">
<value>The key bind you pressed cannot be used, try using a different key bind.</value>
yaira2 marked this conversation as resolved.
Show resolved Hide resolved
</data>
<data name="Customized" xml:space="preserve">
<value>Customized</value>
</data>
Expand Down Expand Up @@ -3823,6 +3826,9 @@
<value>Bitmap Files</value>
<comment>This is the friendly name for bitmap files.</comment>
</data>
<data name="NumPadTypeName" xml:space="preserve">
<value>Num</value>
</data>
<data name="NetworkLocations" xml:space="preserve">
<value>Network locations</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@
<Grid x:Name="PART_ContentRoot">
<TextBlock
x:Name="PART_MainTextTextBlock"
Margin="2,0"
Margin="2"
XTorLukas marked this conversation as resolved.
Show resolved Hide resolved
VerticalAlignment="Top"
Foreground="{ThemeResource TextFillColorTertiaryBrush}"
LineHeight="16"
Expand Down
10 changes: 10 additions & 0 deletions src/Files.App/ViewModels/Settings/ActionsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ public bool IsAlreadyUsedTeachingTipOpened
set => SetProperty(ref _IsAlreadyUsedTeachingTipOpened, value);
}

private bool _IsInvalidKeyTeachingTipOpened;
public bool IsInvalidKeyTeachingTipOpened
{
get => _IsInvalidKeyTeachingTipOpened;
set => SetProperty(ref _IsInvalidKeyTeachingTipOpened, value);
}

private bool _ShowAddNewKeyBindingBlock;
public bool ShowAddNewKeyBindingBlock
{
Expand Down Expand Up @@ -278,6 +285,9 @@ private void ExecuteEditCommand(ModifiableActionItem? item)

// Enter edit mode for the item
item.IsInEditMode = true;

// Mark the key binding as invalid to prevent saving it
item.IsValidKeyBinding = false;
}

private void ExecuteSaveCommand(ModifiableActionItem? item)
Expand Down
9 changes: 9 additions & 0 deletions src/Files.App/Views/Settings/ActionsPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@
AutomationProperties.Name="{helpers:ResourceString Name=Save}"
Command="{Binding ElementName=PageRoot, Path=DataContext.SaveCommand, Mode=OneWay}"
CommandParameter="{x:Bind}"
IsEnabled="{x:Bind IsValidKeyBinding, Mode=OneWay}"
Style="{StaticResource AccentButtonStyle}"
ToolTipService.ToolTip="{helpers:ResourceString Name=Save}">
<FontIcon FontSize="14" Glyph="&#xE73E;" />
Expand Down Expand Up @@ -410,5 +411,13 @@
PreferredPlacement="Auto"
Subtitle="{helpers:ResourceString Name=KeybindingAlreadyUsedNotification}" />

<!-- Invalid Key TeachingTip -->
<TeachingTip
yaira2 marked this conversation as resolved.
Show resolved Hide resolved
x:Name="InvalidKeyTeachingTip"
IsLightDismissEnabled="True"
IsOpen="{x:Bind ViewModel.IsInvalidKeyTeachingTipOpened, Mode=TwoWay}"
PreferredPlacement="Bottom"
Subtitle="{helpers:ResourceString Name=KeybindingInvalidKeyNotification}" />

</Grid>
</Page>
Loading
Loading