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