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