winkeyhook.c revision 05b261ec
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 37/* 38 * References to external symbols 39 */ 40 41extern HHOOK g_hhookKeyboardLL; 42extern DWORD g_dwCurrentThreadID; 43extern HWND g_hwndKeyboardFocus; 44 45 46/* 47 * Function prototypes 48 */ 49 50static LRESULT CALLBACK 51winKeyboardMessageHookLL (int iCode, WPARAM wParam, LPARAM lParam); 52 53 54#ifndef LLKHF_EXTENDED 55# define LLKHF_EXTENDED 0x00000001 56#endif 57#ifndef LLKHF_UP 58# define LLKHF_UP 0x00000080 59#endif 60 61 62/* 63 * KeyboardMessageHook 64 */ 65 66static LRESULT CALLBACK 67winKeyboardMessageHookLL (int iCode, WPARAM wParam, LPARAM lParam) 68{ 69 BOOL fPassKeystroke = FALSE; 70 BOOL fPassAltTab = TRUE; 71 PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam; 72 HWND hwnd = GetActiveWindow(); 73#ifdef XWIN_MULTIWINDOW 74 WindowPtr pWin = NULL; 75 winPrivWinPtr pWinPriv = NULL; 76 winPrivScreenPtr pScreenPriv = NULL; 77 winScreenInfo *pScreenInfo = NULL; 78 79 /* Check if the Windows window property for our X window pointer is valid */ 80 if ((pWin = GetProp (hwnd, WIN_WINDOW_PROP)) != NULL) 81 { 82 /* Get a pointer to our window privates */ 83 pWinPriv = winGetWindowPriv(pWin); 84 85 /* Get pointers to our screen privates and screen info */ 86 pScreenPriv = pWinPriv->pScreenPriv; 87 pScreenInfo = pScreenPriv->pScreenInfo; 88 89 if (pScreenInfo->fMultiWindow) 90 fPassAltTab = FALSE; 91 } 92#endif 93 94 /* Pass keystrokes on to our main message loop */ 95 if (iCode == HC_ACTION) 96 { 97#if 0 98 ErrorF ("vkCode: %08x\tscanCode: %08x\n", p->vkCode, p->scanCode); 99#endif 100 101 switch (wParam) 102 { 103 case WM_KEYDOWN: case WM_SYSKEYDOWN: 104 case WM_KEYUP: case WM_SYSKEYUP: 105 fPassKeystroke = 106 (fPassAltTab && 107 (p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) 108 || (p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN) 109 ; 110 break; 111 } 112 } 113 114 /* 115 * Pass message on to our main message loop. 116 * We process this immediately with SendMessage so that the keystroke 117 * appears in, hopefully, the correct order. 118 */ 119 if (fPassKeystroke) 120 { 121 LPARAM lParamKey = 0x0; 122 123 /* Construct the lParam from KBDLLHOOKSTRUCT */ 124 lParamKey = lParamKey | (0x0000FFFF & 0x00000001); /* Repeat count */ 125 lParamKey = lParamKey | (0x00FF0000 & (p->scanCode << 16)); 126 lParamKey = lParamKey 127 | (0x01000000 & ((p->flags & LLKHF_EXTENDED) << 23)); 128 lParamKey = lParamKey 129 | (0x20000000 130 & ((p->flags & LLKHF_ALTDOWN) << 24)); 131 lParamKey = lParamKey | (0x80000000 & ((p->flags & LLKHF_UP) << 24)); 132 133 /* Send message to our main window that has the keyboard focus */ 134 PostMessage (hwnd, 135 (UINT) wParam, 136 (WPARAM) p->vkCode, 137 lParamKey); 138 139 return 1; 140 } 141 142 /* Call next hook */ 143 return CallNextHookEx (NULL, iCode, wParam, lParam); 144} 145 146 147/* 148 * Attempt to install the keyboard hook, return FALSE if it was not installed 149 */ 150 151Bool 152winInstallKeyboardHookLL () 153{ 154 OSVERSIONINFO osvi = {0}; 155 156 /* Get operating system version information */ 157 osvi.dwOSVersionInfoSize = sizeof (osvi); 158 GetVersionEx (&osvi); 159 160 /* Branch on platform ID */ 161 switch (osvi.dwPlatformId) 162 { 163 case VER_PLATFORM_WIN32_NT: 164 /* Low-level is supported on NT 4.0 SP3+ only */ 165 /* TODO: Return FALSE on NT 4.0 with no SP, SP1, or SP2 */ 166 break; 167 168 case VER_PLATFORM_WIN32_WINDOWS: 169 /* Low-level hook is not supported on non-NT */ 170 return FALSE; 171 } 172 173 /* Install the hook only once */ 174 if (!g_hhookKeyboardLL) 175 g_hhookKeyboardLL = SetWindowsHookEx (WH_KEYBOARD_LL, 176 winKeyboardMessageHookLL, 177 g_hInstance, 178 0); 179 180 return TRUE; 181} 182 183 184/* 185 * Remove the keyboard hook if it is installed 186 */ 187 188void 189winRemoveKeyboardHookLL () 190{ 191 if (g_hhookKeyboardLL) 192 UnhookWindowsHookEx (g_hhookKeyboardLL); 193 g_hhookKeyboardLL = NULL; 194} 195