Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
43 changes: 41 additions & 2 deletions src/InvLock/DataContexts/MainWindowDataContext.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using System.ComponentModel;
using CommunityToolkit.Mvvm.Input;

using SharpHook.Native;

using System.Reflection;

namespace InvLock.DataContexts;

internal class MainWindowDataContext : INotifyPropertyChanged
internal partial class MainWindowDataContext(Func<LockWindow?> lockWindowAccessor)
{
#if DEBUG
public string Title => $"{App.AppName} - Dev {AppVersion}";
Expand All @@ -19,4 +22,40 @@ internal class MainWindowDataContext : INotifyPropertyChanged
public string AppVersion => Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "Unknown";

public Settings Settings { get; } = Settings.Load();

[RelayCommand]
public async Task RecordLockShortcut()
{
LockWindow? lockWindow = lockWindowAccessor();

if (lockWindow is null)
{
return;
}

HashSet<KeyCode>? lockShortcut = await lockWindow.RecordShortcut();

if (lockShortcut is not null)
{
Settings.LockShortcut = lockShortcut;
}
}

[RelayCommand]
public async Task RecordUnlockShortcut()
{
LockWindow? lockWindow = lockWindowAccessor();

if (lockWindow is null)
{
return;
}

HashSet<KeyCode>? unlockShortcut = await lockWindow.RecordShortcut();

if (unlockShortcut is not null)
{
Settings.UnlockShortcut = unlockShortcut;
}
}
}
1 change: 1 addition & 0 deletions src/InvLock/InvLock.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="CuteUtils" Version="1.0.0" />
<PackageReference Include="SharpHook" Version="5.3.8" />
<PackageReference Include="WPF-UI" Version="3.0.5" />
Expand Down
4 changes: 3 additions & 1 deletion src/InvLock/LockWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@
ShowInTaskbar="False"
Title="MainWindow" Height="Auto" Width="Auto">

<controls:OutlinedTextBlock x:Name="textBlock" Text="Lock Screen Active" Bold="True" Stroke="Red" Opacity="0" Fill="Black" StrokeThickness="1" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="50" Font="Segoe UI" />
<Viewbox Stretch="Uniform" StretchDirection="DownOnly">
<controls:OutlinedTextBlock x:Name="textBlock" Text="Lock Screen Active" Bold="True" Stroke="Red" Opacity="0" Fill="Black" StrokeThickness="1" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="50" Font="Segoe UI" />
</Viewbox>
</Window>
102 changes: 90 additions & 12 deletions src/InvLock/LockWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using SharpHook;
using SharpHook.Native;

using System.Diagnostics;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
Expand Down Expand Up @@ -59,6 +60,59 @@ public LockWindow(Settings settings)
_ = Task.Run(hook.Run);
}

public async Task<HashSet<KeyCode>?> RecordShortcut()
{
HashSet<KeyCode> keys = [];

hook.KeyPressed -= Hook_KeyPressed;
hook.KeyPressed += Record;

textBlock.Text = "Press a key combination to record a shortcut";
textBlock.Stroke = Brushes.White;
textBlock.Opacity = 1;

// Wait for the user to press the enter key
await Task.Run(async () =>
{
while (!keys.Contains(KeyCode.VcEnter) && !keys.Contains(KeyCode.VcEscape))
{
await Task.Delay(100);
}
});

hook.KeyPressed -= Record;
hook.KeyPressed += Hook_KeyPressed;

textBlock.Opacity = 0;

if (keys.Contains(KeyCode.VcEscape) || keys.Count <= 1)
{
textBlock.Text = "Shortcut Recording Cancelled";
textBlock.Stroke = (Brush)FindResource("PaletteRedBrush");
Animation();

return null;
}

textBlock.Text = "Shortcut Recorded";
textBlock.Stroke = (Brush)FindResource("PaletteGreenBrush");
Animation();

_ = keys.Remove(KeyCode.VcEnter);

return keys;

void Record(object? sender, KeyboardHookEventArgs e)
{
e.SuppressEvent = true;
_ = keys.Add(e.Data.KeyCode);
Debug.WriteLine(string.Join(" + ", keys.Select(key => key.ToString())));
_ = Dispatcher.Invoke(() => textBlock.Text = string.Join(" + ", keys.Select(key => key.ToString()[2..]))
+ Environment.NewLine
+ "Press ENTER to save or ESCAPE to cancel");
}
}

private void ActivateLockScreen()
{
if (settings.HideWindows)
Expand All @@ -82,8 +136,31 @@ private void ActivateLockScreen()

private void DeactivateLockScreen()
{
isOpen = false;
Dispatcher.Invoke(Close);
if (settings.UseWindowsLockScreen)
{
isOpen = false;

Dispatcher.Invoke(Close);
}
else
{
Dispatcher.Invoke(() =>
{
suppressInput = false;

if (settings.HideWindows)
{
RestoreWindows();
}

isOpen = true;

textBlock.Text = settings.UnlockText;
textBlock.Stroke = (Brush)FindResource("PaletteGreenBrush");

Animation();
});
}
}

private void Hook_KeyPressed(object? sender, KeyboardHookEventArgs e)
Expand All @@ -97,16 +174,13 @@ private void Hook_KeyPressed(object? sender, KeyboardHookEventArgs e)
}
_ = pressedKeys[e.Data.KeyCode] = DateTime.UtcNow;

if (pressedKeys.ContainsKey(KeyCode.VcL) && pressedKeys.ContainsKey(KeyCode.VcLeftShift) && pressedKeys.ContainsKey(KeyCode.VcLeftControl) && pressedKeys.Count == 3)
if (pressedKeys.All(kvp => settings.UnlockShortcut.Contains(kvp.Key)) && suppressInput && pressedKeys.Count == settings.UnlockShortcut.Count)
{
if (suppressInput)
{
DeactivateLockScreen();
}
else
{
ActivateLockScreen();
}
DeactivateLockScreen();
}
else if (pressedKeys.All(kvp => settings.LockShortcut.Contains(kvp.Key)) && !suppressInput && pressedKeys.Count == settings.LockShortcut.Count)
{
ActivateLockScreen();
}

e.SuppressEvent = suppressInput;
Expand Down Expand Up @@ -171,7 +245,11 @@ private void RestoreWindows()

private void Animation()
{
Storyboard storyboard = new Storyboard();
Storyboard storyboard = new Storyboard
{
FillBehavior = FillBehavior.Stop
};

TimeSpan duration = TimeSpan.FromMilliseconds(500);

DoubleAnimation fadeInAnimation = new DoubleAnimation()
Expand Down
56 changes: 44 additions & 12 deletions src/InvLock/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@
It is designed to be lightweight and easy to use.
<LineBreak />
If you have any issues or feature requests, please report them on GitHub.
<LineBreak />
<LineBreak />
To lock and unlock your screen, press
<ui:TextBlock Foreground="{DynamicResource AccentTextFillColorPrimaryBrush}">WIN + SHIFT + L</ui:TextBlock>
</ui:TextBlock>

<ui:TextBlock Margin="0,0,0,8" FontTypography="BodyStrong" Text="Appearance &amp; behavior" />
Expand All @@ -76,7 +72,7 @@
</ui:HyperlinkButton>
</Grid>
</ui:CardControl.Header>
<ComboBox Grid.Column="1" MinWidth="200" SelectedIndex="0">
<ComboBox Grid.Column="1" MinWidth="200" SelectedIndex="0" SelectedValue="{Binding Settings.Theme}" SelectedValuePath="Content">
<ComboBoxItem Content="Windows default" />
<ComboBoxItem Content="Light" />
<ComboBoxItem Content="Dark" />
Expand All @@ -90,20 +86,41 @@
<ui:ToggleSwitch Grid.Column="1" IsChecked="{Binding Settings.HideWindows}" OffContent="Off" OnContent="On" />
</ui:CardControl>

<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=WindowShield24}" Height="75">
<ui:CardControl.Header>
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Use windows lock screen to unlock" />
</ui:CardControl.Header>
<ui:ToggleSwitch Grid.Column="1" IsChecked="{Binding Settings.UseWindowsLockScreen}" OffContent="Off" OnContent="On" />
</ui:CardControl>

<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=LockClosed24}" Height="75">
<ui:CardControl.Header>
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Lock text" />
</ui:CardControl.Header>
<ui:TextBox Grid.Column="1" MinWidth="200" Text="{Binding Settings.LockText, UpdateSourceTrigger=PropertyChanged}" PlaceholderText="Type your lock text here" />
</ui:CardControl>

<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=LockClosed24}" Height="75">
<ui:CardControl.Header>
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Lock shortcut" />
</ui:CardControl.Header>
<ui:Button Grid.Column="1" Command="{Binding RecordLockShortcutCommand}" MinWidth="200" Icon="{ui:SymbolIcon Symbol=Edit24}" Content="{Binding Settings.LockShortcutText}" />
</ui:CardControl>

<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=LockOpen24}" Height="75">
<ui:CardControl.Header>
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Unlock text" />
</ui:CardControl.Header>
<ui:TextBox Grid.Column="1" MinWidth="200" Text="{Binding Settings.UnlockText, UpdateSourceTrigger=PropertyChanged}" PlaceholderText="Type your unlock text here" />
</ui:CardControl>

<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=LockOpen24}" Height="75">
<ui:CardControl.Header>
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Unlock shortcut" />
</ui:CardControl.Header>
<ui:Button Grid.Column="1" Command="{Binding RecordUnlockShortcutCommand}" MinWidth="200" Icon="{ui:SymbolIcon Symbol=Edit24}" Content="{Binding Settings.UnlockShortcutText}" />
</ui:CardControl>

<ui:TextBlock Margin="0,24,0,8" FontTypography="BodyStrong" Text="About" />
<ui:CardExpander ContentPadding="0">
<ui:CardExpander.Header>
Expand All @@ -129,7 +146,26 @@
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Report an issue or request a feature" />
<ui:SymbolIcon Grid.Column="1" Symbol="Link24" />
<StackPanel Grid.Column="1" Orientation="Horizontal">
<ui:SymbolIcon Margin="0 0 6 0" Symbol="Link24" />
<TextBlock Foreground="{ui:ThemeResource TextFillColorSecondaryBrush}" Text="https://github.com/Stone-Red-Code/InvLock/issues" />
</StackPanel>
</Grid>
</ui:Anchor>

<Separator />

<ui:Anchor Margin="0" Padding="16" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Background="Transparent" CornerRadius="0" BorderThickness="0" NavigateUri="https://github.com/Stone-Red-Code/InvLock">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="GitHub" />
<StackPanel Grid.Column="1" Orientation="Horizontal">
<ui:SymbolIcon Margin="0 0 6 0" Symbol="Link24" />
<TextBlock Foreground="{ui:ThemeResource TextFillColorSecondaryBrush}" Text="https://github.com/Stone-Red-Code/InvLock" />
</StackPanel>
</Grid>
</ui:Anchor>

Expand All @@ -140,13 +176,9 @@
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Clone repository" />
<TextBlock Grid.Column="1" Foreground="{ui:ThemeResource TextFillColorSecondaryBrush}" Text="git clone https://github.com/Stone-Red-Code/InvLock" />
<TextBlock Grid.Column="0" Text="Version" />
<TextBlock Grid.Column="1" Foreground="{ui:ThemeResource TextFillColorSecondaryBrush}" Text="{Binding AppVersion}" />
</Grid>

<Separator />

<TextBlock Margin="16" Text="{Binding AppVersion, StringFormat='Version {0}'}" />
</StackPanel>
</ui:CardExpander>
</StackPanel>
Expand Down
3 changes: 2 additions & 1 deletion src/InvLock/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ namespace InvLock;
/// </summary>
public partial class MainWindow : FluentWindow
{
private readonly MainWindowDataContext mainWindowDataContext = new MainWindowDataContext();
private readonly MainWindowDataContext mainWindowDataContext;
private LockWindow? lockWindow;
private bool blockWindowClosing = true;

public MainWindow()
{
mainWindowDataContext = new MainWindowDataContext(() => lockWindow);
DataContext = mainWindowDataContext;

InitializeComponent();
Expand Down
Loading