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