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