winkeyhook.c revision 9ace9065
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 379ace9065Smrgstatic HHOOK g_hhookKeyboardLL = NULL; 3805b261ecSmrg 3905b261ecSmrg 4005b261ecSmrg/* 4105b261ecSmrg * Function prototypes 4205b261ecSmrg */ 4305b261ecSmrg 4405b261ecSmrgstatic LRESULT CALLBACK 4505b261ecSmrgwinKeyboardMessageHookLL (int iCode, WPARAM wParam, LPARAM lParam); 4605b261ecSmrg 4705b261ecSmrg 4805b261ecSmrg#ifndef LLKHF_EXTENDED 4905b261ecSmrg# define LLKHF_EXTENDED 0x00000001 5005b261ecSmrg#endif 5105b261ecSmrg#ifndef LLKHF_UP 5205b261ecSmrg# define LLKHF_UP 0x00000080 5305b261ecSmrg#endif 5405b261ecSmrg 5505b261ecSmrg 5605b261ecSmrg/* 5705b261ecSmrg * KeyboardMessageHook 5805b261ecSmrg */ 5905b261ecSmrg 6005b261ecSmrgstatic LRESULT CALLBACK 6105b261ecSmrgwinKeyboardMessageHookLL (int iCode, WPARAM wParam, LPARAM lParam) 6205b261ecSmrg{ 6305b261ecSmrg BOOL fPassKeystroke = FALSE; 6405b261ecSmrg BOOL fPassAltTab = TRUE; 6505b261ecSmrg PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam; 6605b261ecSmrg HWND hwnd = GetActiveWindow(); 6705b261ecSmrg#ifdef XWIN_MULTIWINDOW 6805b261ecSmrg WindowPtr pWin = NULL; 6905b261ecSmrg winPrivWinPtr pWinPriv = NULL; 7005b261ecSmrg winPrivScreenPtr pScreenPriv = NULL; 7105b261ecSmrg winScreenInfo *pScreenInfo = NULL; 7205b261ecSmrg 7305b261ecSmrg /* Check if the Windows window property for our X window pointer is valid */ 7405b261ecSmrg if ((pWin = GetProp (hwnd, WIN_WINDOW_PROP)) != NULL) 7505b261ecSmrg { 7605b261ecSmrg /* Get a pointer to our window privates */ 7705b261ecSmrg pWinPriv = winGetWindowPriv(pWin); 7805b261ecSmrg 7905b261ecSmrg /* Get pointers to our screen privates and screen info */ 8005b261ecSmrg pScreenPriv = pWinPriv->pScreenPriv; 8105b261ecSmrg pScreenInfo = pScreenPriv->pScreenInfo; 8205b261ecSmrg 8305b261ecSmrg if (pScreenInfo->fMultiWindow) 8405b261ecSmrg fPassAltTab = FALSE; 8505b261ecSmrg } 8605b261ecSmrg#endif 8705b261ecSmrg 8805b261ecSmrg /* Pass keystrokes on to our main message loop */ 8905b261ecSmrg if (iCode == HC_ACTION) 9005b261ecSmrg { 919ace9065Smrg winDebug("winKeyboardMessageHook: vkCode: %08x scanCode: %08x\n", p->vkCode, p->scanCode); 9205b261ecSmrg 9305b261ecSmrg switch (wParam) 9405b261ecSmrg { 9505b261ecSmrg case WM_KEYDOWN: case WM_SYSKEYDOWN: 9605b261ecSmrg case WM_KEYUP: case WM_SYSKEYUP: 9705b261ecSmrg fPassKeystroke = 9805b261ecSmrg (fPassAltTab && 9905b261ecSmrg (p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) 10005b261ecSmrg || (p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN) 10105b261ecSmrg ; 10205b261ecSmrg break; 10305b261ecSmrg } 10405b261ecSmrg } 10505b261ecSmrg 10605b261ecSmrg /* 10705b261ecSmrg * Pass message on to our main message loop. 10805b261ecSmrg * We process this immediately with SendMessage so that the keystroke 10905b261ecSmrg * appears in, hopefully, the correct order. 11005b261ecSmrg */ 11105b261ecSmrg if (fPassKeystroke) 11205b261ecSmrg { 11305b261ecSmrg LPARAM lParamKey = 0x0; 11405b261ecSmrg 11505b261ecSmrg /* Construct the lParam from KBDLLHOOKSTRUCT */ 11605b261ecSmrg lParamKey = lParamKey | (0x0000FFFF & 0x00000001); /* Repeat count */ 11705b261ecSmrg lParamKey = lParamKey | (0x00FF0000 & (p->scanCode << 16)); 11805b261ecSmrg lParamKey = lParamKey 11905b261ecSmrg | (0x01000000 & ((p->flags & LLKHF_EXTENDED) << 23)); 12005b261ecSmrg lParamKey = lParamKey 12105b261ecSmrg | (0x20000000 12205b261ecSmrg & ((p->flags & LLKHF_ALTDOWN) << 24)); 12305b261ecSmrg lParamKey = lParamKey | (0x80000000 & ((p->flags & LLKHF_UP) << 24)); 12405b261ecSmrg 12505b261ecSmrg /* Send message to our main window that has the keyboard focus */ 12605b261ecSmrg PostMessage (hwnd, 12705b261ecSmrg (UINT) wParam, 12805b261ecSmrg (WPARAM) p->vkCode, 12905b261ecSmrg lParamKey); 13005b261ecSmrg 13105b261ecSmrg return 1; 13205b261ecSmrg } 13305b261ecSmrg 13405b261ecSmrg /* Call next hook */ 13505b261ecSmrg return CallNextHookEx (NULL, iCode, wParam, lParam); 13605b261ecSmrg} 13705b261ecSmrg 13805b261ecSmrg 13905b261ecSmrg/* 14005b261ecSmrg * Attempt to install the keyboard hook, return FALSE if it was not installed 14105b261ecSmrg */ 14205b261ecSmrg 14305b261ecSmrgBool 1446747b715SmrgwinInstallKeyboardHookLL (void) 14505b261ecSmrg{ 14605b261ecSmrg OSVERSIONINFO osvi = {0}; 14705b261ecSmrg 14805b261ecSmrg /* Get operating system version information */ 14905b261ecSmrg osvi.dwOSVersionInfoSize = sizeof (osvi); 15005b261ecSmrg GetVersionEx (&osvi); 15105b261ecSmrg 15205b261ecSmrg /* Branch on platform ID */ 15305b261ecSmrg switch (osvi.dwPlatformId) 15405b261ecSmrg { 15505b261ecSmrg case VER_PLATFORM_WIN32_NT: 15605b261ecSmrg /* Low-level is supported on NT 4.0 SP3+ only */ 15705b261ecSmrg /* TODO: Return FALSE on NT 4.0 with no SP, SP1, or SP2 */ 15805b261ecSmrg break; 15905b261ecSmrg 16005b261ecSmrg case VER_PLATFORM_WIN32_WINDOWS: 16105b261ecSmrg /* Low-level hook is not supported on non-NT */ 16205b261ecSmrg return FALSE; 16305b261ecSmrg } 16405b261ecSmrg 16505b261ecSmrg /* Install the hook only once */ 16605b261ecSmrg if (!g_hhookKeyboardLL) 16705b261ecSmrg g_hhookKeyboardLL = SetWindowsHookEx (WH_KEYBOARD_LL, 16805b261ecSmrg winKeyboardMessageHookLL, 16905b261ecSmrg g_hInstance, 17005b261ecSmrg 0); 17105b261ecSmrg 17205b261ecSmrg return TRUE; 17305b261ecSmrg} 17405b261ecSmrg 17505b261ecSmrg 17605b261ecSmrg/* 17705b261ecSmrg * Remove the keyboard hook if it is installed 17805b261ecSmrg */ 17905b261ecSmrg 18005b261ecSmrgvoid 1816747b715SmrgwinRemoveKeyboardHookLL (void) 18205b261ecSmrg{ 18305b261ecSmrg if (g_hhookKeyboardLL) 18405b261ecSmrg UnhookWindowsHookEx (g_hhookKeyboardLL); 18505b261ecSmrg g_hhookKeyboardLL = NULL; 18605b261ecSmrg} 187