winkeyhook.c revision 05b261ec
105b261ecSmrg/* 205b261ecSmrg *Copyright (C) 2004 Harold L Hunt II All Rights Reserved. 305b261ecSmrg * 405b261ecSmrg *Permission is hereby granted, free of charge, to any person obtaining 505b261ecSmrg * a copy of this software and associated documentation files (the 605b261ecSmrg *"Software"), to deal in the Software without restriction, including 705b261ecSmrg *without limitation the rights to use, copy, modify, merge, publish, 805b261ecSmrg *distribute, sublicense, and/or sell copies of the Software, and to 905b261ecSmrg *permit persons to whom the Software is furnished to do so, subject to 1005b261ecSmrg *the following conditions: 1105b261ecSmrg * 1205b261ecSmrg *The above copyright notice and this permission notice shall be 1305b261ecSmrg *included in all copies or substantial portions of the Software. 1405b261ecSmrg * 1505b261ecSmrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1605b261ecSmrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1705b261ecSmrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1805b261ecSmrg *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR 1905b261ecSmrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 2005b261ecSmrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2105b261ecSmrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2205b261ecSmrg * 2305b261ecSmrg *Except as contained in this notice, the name of Harold L Hunt II 2405b261ecSmrg *shall not be used in advertising or otherwise to promote the sale, use 2505b261ecSmrg *or other dealings in this Software without prior written authorization 2605b261ecSmrg *from Harold L Hunt II. 2705b261ecSmrg * 2805b261ecSmrg * Authors: Harold L Hunt II 2905b261ecSmrg */ 3005b261ecSmrg 3105b261ecSmrg#ifdef HAVE_XWIN_CONFIG_H 3205b261ecSmrg#include <xwin-config.h> 3305b261ecSmrg#endif 3405b261ecSmrg#include "win.h" 3505b261ecSmrg 3605b261ecSmrg 3705b261ecSmrg/* 3805b261ecSmrg * References to external symbols 3905b261ecSmrg */ 4005b261ecSmrg 4105b261ecSmrgextern HHOOK g_hhookKeyboardLL; 4205b261ecSmrgextern DWORD g_dwCurrentThreadID; 4305b261ecSmrgextern HWND g_hwndKeyboardFocus; 4405b261ecSmrg 4505b261ecSmrg 4605b261ecSmrg/* 4705b261ecSmrg * Function prototypes 4805b261ecSmrg */ 4905b261ecSmrg 5005b261ecSmrgstatic LRESULT CALLBACK 5105b261ecSmrgwinKeyboardMessageHookLL (int iCode, WPARAM wParam, LPARAM lParam); 5205b261ecSmrg 5305b261ecSmrg 5405b261ecSmrg#ifndef LLKHF_EXTENDED 5505b261ecSmrg# define LLKHF_EXTENDED 0x00000001 5605b261ecSmrg#endif 5705b261ecSmrg#ifndef LLKHF_UP 5805b261ecSmrg# define LLKHF_UP 0x00000080 5905b261ecSmrg#endif 6005b261ecSmrg 6105b261ecSmrg 6205b261ecSmrg/* 6305b261ecSmrg * KeyboardMessageHook 6405b261ecSmrg */ 6505b261ecSmrg 6605b261ecSmrgstatic LRESULT CALLBACK 6705b261ecSmrgwinKeyboardMessageHookLL (int iCode, WPARAM wParam, LPARAM lParam) 6805b261ecSmrg{ 6905b261ecSmrg BOOL fPassKeystroke = FALSE; 7005b261ecSmrg BOOL fPassAltTab = TRUE; 7105b261ecSmrg PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam; 7205b261ecSmrg HWND hwnd = GetActiveWindow(); 7305b261ecSmrg#ifdef XWIN_MULTIWINDOW 7405b261ecSmrg WindowPtr pWin = NULL; 7505b261ecSmrg winPrivWinPtr pWinPriv = NULL; 7605b261ecSmrg winPrivScreenPtr pScreenPriv = NULL; 7705b261ecSmrg winScreenInfo *pScreenInfo = NULL; 7805b261ecSmrg 7905b261ecSmrg /* Check if the Windows window property for our X window pointer is valid */ 8005b261ecSmrg if ((pWin = GetProp (hwnd, WIN_WINDOW_PROP)) != NULL) 8105b261ecSmrg { 8205b261ecSmrg /* Get a pointer to our window privates */ 8305b261ecSmrg pWinPriv = winGetWindowPriv(pWin); 8405b261ecSmrg 8505b261ecSmrg /* Get pointers to our screen privates and screen info */ 8605b261ecSmrg pScreenPriv = pWinPriv->pScreenPriv; 8705b261ecSmrg pScreenInfo = pScreenPriv->pScreenInfo; 8805b261ecSmrg 8905b261ecSmrg if (pScreenInfo->fMultiWindow) 9005b261ecSmrg fPassAltTab = FALSE; 9105b261ecSmrg } 9205b261ecSmrg#endif 9305b261ecSmrg 9405b261ecSmrg /* Pass keystrokes on to our main message loop */ 9505b261ecSmrg if (iCode == HC_ACTION) 9605b261ecSmrg { 9705b261ecSmrg#if 0 9805b261ecSmrg ErrorF ("vkCode: %08x\tscanCode: %08x\n", p->vkCode, p->scanCode); 9905b261ecSmrg#endif 10005b261ecSmrg 10105b261ecSmrg switch (wParam) 10205b261ecSmrg { 10305b261ecSmrg case WM_KEYDOWN: case WM_SYSKEYDOWN: 10405b261ecSmrg case WM_KEYUP: case WM_SYSKEYUP: 10505b261ecSmrg fPassKeystroke = 10605b261ecSmrg (fPassAltTab && 10705b261ecSmrg (p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) 10805b261ecSmrg || (p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN) 10905b261ecSmrg ; 11005b261ecSmrg break; 11105b261ecSmrg } 11205b261ecSmrg } 11305b261ecSmrg 11405b261ecSmrg /* 11505b261ecSmrg * Pass message on to our main message loop. 11605b261ecSmrg * We process this immediately with SendMessage so that the keystroke 11705b261ecSmrg * appears in, hopefully, the correct order. 11805b261ecSmrg */ 11905b261ecSmrg if (fPassKeystroke) 12005b261ecSmrg { 12105b261ecSmrg LPARAM lParamKey = 0x0; 12205b261ecSmrg 12305b261ecSmrg /* Construct the lParam from KBDLLHOOKSTRUCT */ 12405b261ecSmrg lParamKey = lParamKey | (0x0000FFFF & 0x00000001); /* Repeat count */ 12505b261ecSmrg lParamKey = lParamKey | (0x00FF0000 & (p->scanCode << 16)); 12605b261ecSmrg lParamKey = lParamKey 12705b261ecSmrg | (0x01000000 & ((p->flags & LLKHF_EXTENDED) << 23)); 12805b261ecSmrg lParamKey = lParamKey 12905b261ecSmrg | (0x20000000 13005b261ecSmrg & ((p->flags & LLKHF_ALTDOWN) << 24)); 13105b261ecSmrg lParamKey = lParamKey | (0x80000000 & ((p->flags & LLKHF_UP) << 24)); 13205b261ecSmrg 13305b261ecSmrg /* Send message to our main window that has the keyboard focus */ 13405b261ecSmrg PostMessage (hwnd, 13505b261ecSmrg (UINT) wParam, 13605b261ecSmrg (WPARAM) p->vkCode, 13705b261ecSmrg lParamKey); 13805b261ecSmrg 13905b261ecSmrg return 1; 14005b261ecSmrg } 14105b261ecSmrg 14205b261ecSmrg /* Call next hook */ 14305b261ecSmrg return CallNextHookEx (NULL, iCode, wParam, lParam); 14405b261ecSmrg} 14505b261ecSmrg 14605b261ecSmrg 14705b261ecSmrg/* 14805b261ecSmrg * Attempt to install the keyboard hook, return FALSE if it was not installed 14905b261ecSmrg */ 15005b261ecSmrg 15105b261ecSmrgBool 15205b261ecSmrgwinInstallKeyboardHookLL () 15305b261ecSmrg{ 15405b261ecSmrg OSVERSIONINFO osvi = {0}; 15505b261ecSmrg 15605b261ecSmrg /* Get operating system version information */ 15705b261ecSmrg osvi.dwOSVersionInfoSize = sizeof (osvi); 15805b261ecSmrg GetVersionEx (&osvi); 15905b261ecSmrg 16005b261ecSmrg /* Branch on platform ID */ 16105b261ecSmrg switch (osvi.dwPlatformId) 16205b261ecSmrg { 16305b261ecSmrg case VER_PLATFORM_WIN32_NT: 16405b261ecSmrg /* Low-level is supported on NT 4.0 SP3+ only */ 16505b261ecSmrg /* TODO: Return FALSE on NT 4.0 with no SP, SP1, or SP2 */ 16605b261ecSmrg break; 16705b261ecSmrg 16805b261ecSmrg case VER_PLATFORM_WIN32_WINDOWS: 16905b261ecSmrg /* Low-level hook is not supported on non-NT */ 17005b261ecSmrg return FALSE; 17105b261ecSmrg } 17205b261ecSmrg 17305b261ecSmrg /* Install the hook only once */ 17405b261ecSmrg if (!g_hhookKeyboardLL) 17505b261ecSmrg g_hhookKeyboardLL = SetWindowsHookEx (WH_KEYBOARD_LL, 17605b261ecSmrg winKeyboardMessageHookLL, 17705b261ecSmrg g_hInstance, 17805b261ecSmrg 0); 17905b261ecSmrg 18005b261ecSmrg return TRUE; 18105b261ecSmrg} 18205b261ecSmrg 18305b261ecSmrg 18405b261ecSmrg/* 18505b261ecSmrg * Remove the keyboard hook if it is installed 18605b261ecSmrg */ 18705b261ecSmrg 18805b261ecSmrgvoid 18905b261ecSmrgwinRemoveKeyboardHookLL () 19005b261ecSmrg{ 19105b261ecSmrg if (g_hhookKeyboardLL) 19205b261ecSmrg UnhookWindowsHookEx (g_hhookKeyboardLL); 19305b261ecSmrg g_hhookKeyboardLL = NULL; 19405b261ecSmrg} 195