-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Replace global windows hook with hotkey
- Loading branch information
Showing
9 changed files
with
185 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
src/Jarvis/Infrastructure/Input/Hooks/HotKeyKeyboardHook.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// Licensed to Spectre Systems AB under one or more agreements. | ||
// Spectre Systems AB licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Windows.Input; | ||
using System.Windows.Interop; | ||
using Jarvis.Core.Interop; | ||
|
||
namespace Jarvis.Infrastructure.Input | ||
{ | ||
public sealed class HotKeyKeyboardHook : IKeyboardHook | ||
{ | ||
private readonly Action _action; | ||
private int _id; | ||
private bool _disposed; | ||
|
||
private static Dictionary<int, HotKeyKeyboardHook> _lookup; | ||
|
||
public HotKeyKeyboardHook(Action action) | ||
{ | ||
_action = action; | ||
} | ||
|
||
public void Register() | ||
{ | ||
var virtualKeyCode = KeyInterop.VirtualKeyFromKey(Key.Space); | ||
_id = virtualKeyCode + 65536; | ||
|
||
var result = Win32.Keyboard.HotKey.RegisterHotKey(IntPtr.Zero, _id, 0x0001, (uint)virtualKeyCode); | ||
if (!result) | ||
{ | ||
throw new InvalidOperationException("Could not register hotkey."); | ||
} | ||
|
||
if (_lookup == null) | ||
{ | ||
_lookup = new Dictionary<int, HotKeyKeyboardHook>(); | ||
ComponentDispatcher.ThreadFilterMessage += OnThreadFilterMessage; | ||
} | ||
|
||
_lookup.Add(_id, this); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
if (!_disposed) | ||
{ | ||
Win32.Keyboard.HotKey.UnregisterHotKey(IntPtr.Zero, _id); | ||
_disposed = true; | ||
} | ||
} | ||
|
||
private static void OnThreadFilterMessage(ref MSG msg, ref bool handled) | ||
{ | ||
if (!handled) | ||
{ | ||
if (msg.message == Win32.Keyboard.HotKey.WmHotKey) | ||
{ | ||
if (_lookup.TryGetValue((int)msg.wParam, out var hotKey)) | ||
{ | ||
hotKey._action?.Invoke(); | ||
handled = true; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// Licensed to Spectre Systems AB under one or more agreements. | ||
// Spectre Systems AB licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System; | ||
|
||
namespace Jarvis.Infrastructure.Input | ||
{ | ||
public interface IKeyboardHook : IDisposable | ||
{ | ||
void Register(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// Licensed to Spectre Systems AB under one or more agreements. | ||
// Spectre Systems AB licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System; | ||
using Jarvis.Core; | ||
using Jarvis.Core.Diagnostics; | ||
using Jarvis.Infrastructure.Input; | ||
|
||
namespace Jarvis.Services | ||
{ | ||
public sealed class KeyboardService : IInitializable, IDisposable | ||
{ | ||
private readonly ApplicationService _applicationService; | ||
private readonly IJarvisLog _log; | ||
private IKeyboardHook _hook; | ||
|
||
public KeyboardService(ApplicationService applicationService, IJarvisLog log) | ||
{ | ||
_applicationService = applicationService; | ||
_log = new LogDecorator(nameof(KeyboardService), log); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
_hook?.Dispose(); | ||
} | ||
|
||
public void Initialize() | ||
{ | ||
try | ||
{ | ||
_log.Information("Registering Windows hot key..."); | ||
_hook = new HotKeyKeyboardHook(() => _applicationService.Toggle()); | ||
_hook.Register(); | ||
_log.Information("Hot key was successfully registered."); | ||
} | ||
catch (Exception ex) | ||
{ | ||
_log.Error($"An error occured when registering hot key: {ex.Message}"); | ||
|
||
try | ||
{ | ||
_log.Information("Registering windows keyboard hook..."); | ||
_hook = new GlobalKeyboardHook(() => _applicationService.Toggle()); | ||
_hook.Register(); | ||
_log.Information("Keyboard hook was successfully registered."); | ||
} | ||
catch (Exception ex2) | ||
{ | ||
// TODO: Notify the user that registering wasn't possible. | ||
_log.Error($"Unable to register windows keyboard hook: {ex2.Message}"); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters