winkeyhook.c (4818B)
1 /* 2 *Copyright (C) 2004 Harold L Hunt II All Rights Reserved. 3 * 4 *Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files (the 6 *"Software"), to deal in the Software without restriction, including 7 *without limitation the rights to use, copy, modify, merge, publish, 8 *distribute, sublicense, and/or sell copies of the Software, and to 9 *permit persons to whom the Software is furnished to do so, subject to 10 *the following conditions: 11 * 12 *The above copyright notice and this permission notice shall be 13 *included in all copies or substantial portions of the Software. 14 * 15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR 19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 * 23 *Except as contained in this notice, the name of Harold L Hunt II 24 *shall not be used in advertising or otherwise to promote the sale, use 25 *or other dealings in this Software without prior written authorization 26 *from Harold L Hunt II. 27 * 28 * Authors: Harold L Hunt II 29 */ 30 31 #ifdef HAVE_XWIN_CONFIG_H 32 #include <xwin-config.h> 33 #endif 34 #include "win.h" 35 36 static HHOOK g_hhookKeyboardLL = NULL; 37 38 /* 39 * Function prototypes 40 */ 41 42 static LRESULT CALLBACK 43 winKeyboardMessageHookLL(int iCode, WPARAM wParam, LPARAM lParam); 44 45 #ifndef LLKHF_EXTENDED 46 #define LLKHF_EXTENDED 0x00000001 47 #endif 48 #ifndef LLKHF_UP 49 #define LLKHF_UP 0x00000080 50 #endif 51 52 /* 53 * KeyboardMessageHook 54 */ 55 56 static LRESULT CALLBACK 57 winKeyboardMessageHookLL(int iCode, WPARAM wParam, LPARAM lParam) 58 { 59 BOOL fPassKeystroke = FALSE; 60 BOOL fPassAltTab = TRUE; 61 PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam; 62 HWND hwnd = GetActiveWindow(); 63 64 WindowPtr pWin = NULL; 65 winPrivWinPtr pWinPriv = NULL; 66 winPrivScreenPtr pScreenPriv = NULL; 67 winScreenInfo *pScreenInfo = NULL; 68 69 /* Check if the Windows window property for our X window pointer is valid */ 70 if ((pWin = GetProp(hwnd, WIN_WINDOW_PROP)) != NULL) { 71 /* Get a pointer to our window privates */ 72 pWinPriv = winGetWindowPriv(pWin); 73 74 /* Get pointers to our screen privates and screen info */ 75 pScreenPriv = pWinPriv->pScreenPriv; 76 pScreenInfo = pScreenPriv->pScreenInfo; 77 78 if (pScreenInfo->fMultiWindow) 79 fPassAltTab = FALSE; 80 } 81 82 /* Pass keystrokes on to our main message loop */ 83 if (iCode == HC_ACTION) { 84 winDebug("winKeyboardMessageHook: vkCode: %08x scanCode: %08x\n", 85 (unsigned int)p->vkCode, (unsigned int)p->scanCode); 86 87 switch (wParam) { 88 case WM_KEYDOWN: 89 case WM_SYSKEYDOWN: 90 case WM_KEYUP: 91 case WM_SYSKEYUP: 92 fPassKeystroke = 93 (fPassAltTab && 94 (p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) 95 || (p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN); 96 break; 97 } 98 } 99 100 /* 101 * Pass message on to our main message loop. 102 * We process this immediately with SendMessage so that the keystroke 103 * appears in, hopefully, the correct order. 104 */ 105 if (fPassKeystroke) { 106 LPARAM lParamKey = 0x0; 107 108 /* Construct the lParam from KBDLLHOOKSTRUCT */ 109 lParamKey = lParamKey | (0x0000FFFF & 0x00000001); /* Repeat count */ 110 lParamKey = lParamKey | (0x00FF0000 & (p->scanCode << 16)); 111 lParamKey = lParamKey 112 | (0x01000000 & ((p->flags & LLKHF_EXTENDED) << 23)); 113 lParamKey = lParamKey 114 | (0x20000000 & ((p->flags & LLKHF_ALTDOWN) << 24)); 115 lParamKey = lParamKey | (0x80000000 & ((p->flags & LLKHF_UP) << 24)); 116 117 /* Send message to our main window that has the keyboard focus */ 118 PostMessage(hwnd, (UINT) wParam, (WPARAM) p->vkCode, lParamKey); 119 120 return 1; 121 } 122 123 /* Call next hook */ 124 return CallNextHookEx(NULL, iCode, wParam, lParam); 125 } 126 127 /* 128 * Attempt to install the keyboard hook, return FALSE if it was not installed 129 */ 130 131 Bool 132 winInstallKeyboardHookLL(void) 133 { 134 /* Install the hook only once */ 135 if (!g_hhookKeyboardLL) 136 g_hhookKeyboardLL = SetWindowsHookEx(WH_KEYBOARD_LL, 137 winKeyboardMessageHookLL, 138 g_hInstance, 0); 139 140 return TRUE; 141 } 142 143 /* 144 * Remove the keyboard hook if it is installed 145 */ 146 147 void 148 winRemoveKeyboardHookLL(void) 149 { 150 if (g_hhookKeyboardLL) 151 UnhookWindowsHookEx(g_hhookKeyboardLL); 152 g_hhookKeyboardLL = NULL; 153 }