// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. #nullable disable using System; using System.Runtime.InteropServices; // ReSharper disable IdentifierTypo namespace osu.Desktop.Windows { internal class WindowsKey { private delegate int LowLevelKeyboardProcDelegate(int nCode, int wParam, ref KdDllHookStruct lParam); private static bool isBlocked; private const int wh_keyboard_ll = 13; private const int wm_keydown = 256; private const int wm_syskeyup = 261; //Resharper disable once NotAccessedField.Local private static LowLevelKeyboardProcDelegate keyboardHookDelegate; // keeping a reference alive for the GC private static IntPtr keyHook; [StructLayout(LayoutKind.Explicit)] private readonly struct KdDllHookStruct { [FieldOffset(0)] public readonly int VkCode; [FieldOffset(8)] public readonly int Flags; } private static int lowLevelKeyboardProc(int nCode, int wParam, ref KdDllHookStruct lParam) { if (wParam >= wm_keydown && wParam <= wm_syskeyup) { switch (lParam.VkCode) { case 0x5B: // left windows key case 0x5C: // right windows key return 1; } } return callNextHookEx(0, nCode, wParam, ref lParam); } internal static void Disable() { if (keyHook != IntPtr.Zero || isBlocked) return; keyHook = setWindowsHookEx(wh_keyboard_ll, (keyboardHookDelegate = lowLevelKeyboardProc), Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]), 0); isBlocked = true; } internal static void Enable() { if (keyHook == IntPtr.Zero || !isBlocked) return; keyHook = unhookWindowsHookEx(keyHook); keyboardHookDelegate = null; keyHook = IntPtr.Zero; isBlocked = false; } [DllImport(@"user32.dll", EntryPoint = @"SetWindowsHookExA")] private static extern IntPtr setWindowsHookEx(int idHook, LowLevelKeyboardProcDelegate lpfn, IntPtr hMod, int dwThreadId); [DllImport(@"user32.dll", EntryPoint = @"UnhookWindowsHookEx")] private static extern IntPtr unhookWindowsHookEx(IntPtr hHook); [DllImport(@"user32.dll", EntryPoint = @"CallNextHookEx")] private static extern int callNextHookEx(int hHook, int nCode, int wParam, ref KdDllHookStruct lParam); } }