195 lines
5.1 KiB
C
195 lines
5.1 KiB
C
|
/*
|
||
|
*Copyright (C) 2004 Harold L Hunt II All Rights Reserved.
|
||
|
*
|
||
|
*Permission is hereby granted, free of charge, to any person obtaining
|
||
|
* a copy of this software and associated documentation files (the
|
||
|
*"Software"), to deal in the Software without restriction, including
|
||
|
*without limitation the rights to use, copy, modify, merge, publish,
|
||
|
*distribute, sublicense, and/or sell copies of the Software, and to
|
||
|
*permit persons to whom the Software is furnished to do so, subject to
|
||
|
*the following conditions:
|
||
|
*
|
||
|
*The above copyright notice and this permission notice shall be
|
||
|
*included in all copies or substantial portions of the Software.
|
||
|
*
|
||
|
*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
|
*EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
|
*MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
|
*NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
|
||
|
*ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||
|
*CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||
|
*WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
*
|
||
|
*Except as contained in this notice, the name of Harold L Hunt II
|
||
|
*shall not be used in advertising or otherwise to promote the sale, use
|
||
|
*or other dealings in this Software without prior written authorization
|
||
|
*from Harold L Hunt II.
|
||
|
*
|
||
|
* Authors: Harold L Hunt II
|
||
|
*/
|
||
|
|
||
|
#ifdef HAVE_XWIN_CONFIG_H
|
||
|
#include <xwin-config.h>
|
||
|
#endif
|
||
|
#include "win.h"
|
||
|
|
||
|
|
||
|
/*
|
||
|
* References to external symbols
|
||
|
*/
|
||
|
|
||
|
extern HHOOK g_hhookKeyboardLL;
|
||
|
extern DWORD g_dwCurrentThreadID;
|
||
|
extern HWND g_hwndKeyboardFocus;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Function prototypes
|
||
|
*/
|
||
|
|
||
|
static LRESULT CALLBACK
|
||
|
winKeyboardMessageHookLL (int iCode, WPARAM wParam, LPARAM lParam);
|
||
|
|
||
|
|
||
|
#ifndef LLKHF_EXTENDED
|
||
|
# define LLKHF_EXTENDED 0x00000001
|
||
|
#endif
|
||
|
#ifndef LLKHF_UP
|
||
|
# define LLKHF_UP 0x00000080
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*
|
||
|
* KeyboardMessageHook
|
||
|
*/
|
||
|
|
||
|
static LRESULT CALLBACK
|
||
|
winKeyboardMessageHookLL (int iCode, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
BOOL fPassKeystroke = FALSE;
|
||
|
BOOL fPassAltTab = TRUE;
|
||
|
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam;
|
||
|
HWND hwnd = GetActiveWindow();
|
||
|
#ifdef XWIN_MULTIWINDOW
|
||
|
WindowPtr pWin = NULL;
|
||
|
winPrivWinPtr pWinPriv = NULL;
|
||
|
winPrivScreenPtr pScreenPriv = NULL;
|
||
|
winScreenInfo *pScreenInfo = NULL;
|
||
|
|
||
|
/* Check if the Windows window property for our X window pointer is valid */
|
||
|
if ((pWin = GetProp (hwnd, WIN_WINDOW_PROP)) != NULL)
|
||
|
{
|
||
|
/* Get a pointer to our window privates */
|
||
|
pWinPriv = winGetWindowPriv(pWin);
|
||
|
|
||
|
/* Get pointers to our screen privates and screen info */
|
||
|
pScreenPriv = pWinPriv->pScreenPriv;
|
||
|
pScreenInfo = pScreenPriv->pScreenInfo;
|
||
|
|
||
|
if (pScreenInfo->fMultiWindow)
|
||
|
fPassAltTab = FALSE;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/* Pass keystrokes on to our main message loop */
|
||
|
if (iCode == HC_ACTION)
|
||
|
{
|
||
|
#if 0
|
||
|
ErrorF ("vkCode: %08x\tscanCode: %08x\n", p->vkCode, p->scanCode);
|
||
|
#endif
|
||
|
|
||
|
switch (wParam)
|
||
|
{
|
||
|
case WM_KEYDOWN: case WM_SYSKEYDOWN:
|
||
|
case WM_KEYUP: case WM_SYSKEYUP:
|
||
|
fPassKeystroke =
|
||
|
(fPassAltTab &&
|
||
|
(p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0))
|
||
|
|| (p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN)
|
||
|
;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Pass message on to our main message loop.
|
||
|
* We process this immediately with SendMessage so that the keystroke
|
||
|
* appears in, hopefully, the correct order.
|
||
|
*/
|
||
|
if (fPassKeystroke)
|
||
|
{
|
||
|
LPARAM lParamKey = 0x0;
|
||
|
|
||
|
/* Construct the lParam from KBDLLHOOKSTRUCT */
|
||
|
lParamKey = lParamKey | (0x0000FFFF & 0x00000001); /* Repeat count */
|
||
|
lParamKey = lParamKey | (0x00FF0000 & (p->scanCode << 16));
|
||
|
lParamKey = lParamKey
|
||
|
| (0x01000000 & ((p->flags & LLKHF_EXTENDED) << 23));
|
||
|
lParamKey = lParamKey
|
||
|
| (0x20000000
|
||
|
& ((p->flags & LLKHF_ALTDOWN) << 24));
|
||
|
lParamKey = lParamKey | (0x80000000 & ((p->flags & LLKHF_UP) << 24));
|
||
|
|
||
|
/* Send message to our main window that has the keyboard focus */
|
||
|
PostMessage (hwnd,
|
||
|
(UINT) wParam,
|
||
|
(WPARAM) p->vkCode,
|
||
|
lParamKey);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/* Call next hook */
|
||
|
return CallNextHookEx (NULL, iCode, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Attempt to install the keyboard hook, return FALSE if it was not installed
|
||
|
*/
|
||
|
|
||
|
Bool
|
||
|
winInstallKeyboardHookLL ()
|
||
|
{
|
||
|
OSVERSIONINFO osvi = {0};
|
||
|
|
||
|
/* Get operating system version information */
|
||
|
osvi.dwOSVersionInfoSize = sizeof (osvi);
|
||
|
GetVersionEx (&osvi);
|
||
|
|
||
|
/* Branch on platform ID */
|
||
|
switch (osvi.dwPlatformId)
|
||
|
{
|
||
|
case VER_PLATFORM_WIN32_NT:
|
||
|
/* Low-level is supported on NT 4.0 SP3+ only */
|
||
|
/* TODO: Return FALSE on NT 4.0 with no SP, SP1, or SP2 */
|
||
|
break;
|
||
|
|
||
|
case VER_PLATFORM_WIN32_WINDOWS:
|
||
|
/* Low-level hook is not supported on non-NT */
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/* Install the hook only once */
|
||
|
if (!g_hhookKeyboardLL)
|
||
|
g_hhookKeyboardLL = SetWindowsHookEx (WH_KEYBOARD_LL,
|
||
|
winKeyboardMessageHookLL,
|
||
|
g_hInstance,
|
||
|
0);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Remove the keyboard hook if it is installed
|
||
|
*/
|
||
|
|
||
|
void
|
||
|
winRemoveKeyboardHookLL ()
|
||
|
{
|
||
|
if (g_hhookKeyboardLL)
|
||
|
UnhookWindowsHookEx (g_hhookKeyboardLL);
|
||
|
g_hhookKeyboardLL = NULL;
|
||
|
}
|