diff options
| author | Jussi Lahdenniemi | 2016-02-26 12:51:24 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2016-02-26 12:51:24 +0200 |
| commit | 97d7a0b8db4ce32a8e489dec48634b7e85212eaa (patch) | |
| tree | e1477561851991fe7be1213747d201d744794286 /src | |
| parent | 22994735af588be9c2d6d438155b73328aaa0cf3 (diff) | |
| download | emacs-97d7a0b8db4ce32a8e489dec48634b7e85212eaa.tar.gz emacs-97d7a0b8db4ce32a8e489dec48634b7e85212eaa.zip | |
Improve the register-hotkey functionality on MS-Windows
* src/w32fns.c (_WIN32_WINNT): Define to 0x0600, needed for
keyboard hook functionality.
Include w32inevt.h, basetyps.h and unknwn.h.
(VK_ANY, WM_WTSSESSION_CHANGE, WTS_SESSION_LOCK): New macros.
(kbdhook): A new struct definition.
(funhook, setup_w32_kbdhook, remove_w32_kbdhook, hook_w32_key)
(check_w32_winkey_state, reset_w32_kbdhook_state): New functions.
(modifier_set): Call check_w32_winkey_state if a Win key was
pressed and the keyboard hook is active.
(w32_wnd_proc): Don't handle Win key combinations if the keyboard
hook is active. Only register/unregister the hotkeys if the
keyboard hook is not active. When WM_CREATE is received, call
setup_w32_kbdhook. When WM_DESTROY is received, call
reset_w32_kbdhook_state.
(lookup_vk_code): When the keyboard hook is active, map
alphanumeric characters to themselves.
(w32_parse_and_hook_hot_key): Renamed from w32_parse_hot_key. Map
modified keys to VK_ANY if the keyboard hook is active. Register
Alt-x and Win-x combinations.
(Fw32_shell_execute): Update doc string to reflect new
functionality. Bypass the code that posts the
WM_EMACS_REGISTER_HOT_KEY message if the keyboard hook is active.
(Fw32_unregister_hot_key): Bypass the code that posts the
WM_EMACS_UNREGISTER_HOT_KEY message if the keyboard hook is active.
(syms_of_w32fns) <w32-pass-lwindow-to-system>
<w32-pass-rwindow-to-system, w32-phantom-key-code>
<w32-lwindow-modifier, w32-rwindow-modifier>: Update doc strings
to reflect the new functionality.
* src/w32console.c (initialize_w32_display): Install the low-level
keyboard hook.
* src/w32inevt.c (key_event): Handle Win-x combinations only if
the keyboard hook is not active. If the hook is active, use
check_w32_winkey_state instead.
* src/w32term.h (setup_w32_kbdhook, remove_w32_kbdhook)
(check_w32_winkey_state): Add prototypes.
(w32_kbdhook_active): New macro.
* doc/emacs/msdos.texi (Windows Keyboard): Update to reflect the
new functionality.
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32console.c | 3 | ||||
| -rw-r--r-- | src/w32fns.c | 556 | ||||
| -rw-r--r-- | src/w32inevt.c | 20 | ||||
| -rw-r--r-- | src/w32term.h | 6 |
4 files changed, 541 insertions, 44 deletions
diff --git a/src/w32console.c b/src/w32console.c index 6277f131b50..fdadd48f323 100644 --- a/src/w32console.c +++ b/src/w32console.c | |||
| @@ -759,6 +759,9 @@ initialize_w32_display (struct terminal *term, int *width, int *height) | |||
| 759 | 759 | ||
| 760 | /* Setup w32_display_info structure for this frame. */ | 760 | /* Setup w32_display_info structure for this frame. */ |
| 761 | w32_initialize_display_info (build_string ("Console")); | 761 | w32_initialize_display_info (build_string ("Console")); |
| 762 | |||
| 763 | /* Set up the keyboard hook. */ | ||
| 764 | setup_w32_kbdhook (); | ||
| 762 | } | 765 | } |
| 763 | 766 | ||
| 764 | 767 | ||
diff --git a/src/w32fns.c b/src/w32fns.c index a5018ae9d30..10c8af71073 100644 --- a/src/w32fns.c +++ b/src/w32fns.c | |||
| @@ -20,6 +20,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 20 | /* Added by Kevin Gallo */ | 20 | /* Added by Kevin Gallo */ |
| 21 | 21 | ||
| 22 | #include <config.h> | 22 | #include <config.h> |
| 23 | /* Override API version to get the latest functionality. */ | ||
| 24 | #undef _WIN32_WINNT | ||
| 25 | #define _WIN32_WINNT 0x0600 | ||
| 23 | 26 | ||
| 24 | #include <signal.h> | 27 | #include <signal.h> |
| 25 | #include <stdio.h> | 28 | #include <stdio.h> |
| @@ -41,6 +44,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 41 | #include "coding.h" | 44 | #include "coding.h" |
| 42 | 45 | ||
| 43 | #include "w32common.h" | 46 | #include "w32common.h" |
| 47 | #include "w32inevt.h" | ||
| 44 | 48 | ||
| 45 | #ifdef WINDOWSNT | 49 | #ifdef WINDOWSNT |
| 46 | #include <mbstring.h> | 50 | #include <mbstring.h> |
| @@ -52,6 +56,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 52 | #include "w32.h" | 56 | #include "w32.h" |
| 53 | #endif | 57 | #endif |
| 54 | 58 | ||
| 59 | #include <basetyps.h> | ||
| 60 | #include <unknwn.h> | ||
| 55 | #include <commctrl.h> | 61 | #include <commctrl.h> |
| 56 | #include <commdlg.h> | 62 | #include <commdlg.h> |
| 57 | #include <shellapi.h> | 63 | #include <shellapi.h> |
| @@ -251,6 +257,38 @@ HINSTANCE hinst = NULL; | |||
| 251 | static unsigned int sound_type = 0xFFFFFFFF; | 257 | static unsigned int sound_type = 0xFFFFFFFF; |
| 252 | #define MB_EMACS_SILENT (0xFFFFFFFF - 1) | 258 | #define MB_EMACS_SILENT (0xFFFFFFFF - 1) |
| 253 | 259 | ||
| 260 | /* Special virtual key code for indicating "any" key. */ | ||
| 261 | #define VK_ANY 0xFF | ||
| 262 | |||
| 263 | #ifndef WM_WTSSESSION_CHANGE | ||
| 264 | /* 32-bit MinGW does not define these constants. */ | ||
| 265 | # define WM_WTSSESSION_CHANGE 0x02B1 | ||
| 266 | # define WTS_SESSION_LOCK 0x7 | ||
| 267 | #endif | ||
| 268 | |||
| 269 | /* Keyboard hook state data. */ | ||
| 270 | static struct | ||
| 271 | { | ||
| 272 | int hook_count; /* counter, if several windows are created */ | ||
| 273 | HHOOK hook; /* hook handle */ | ||
| 274 | HWND console; /* console window handle */ | ||
| 275 | |||
| 276 | int lwindown; /* Left Windows key currently pressed (and hooked) */ | ||
| 277 | int rwindown; /* Right Windows key currently pressed (and hooked) */ | ||
| 278 | int winsdown; /* Number of handled keys currently pressed */ | ||
| 279 | int send_win_up; /* Pass through the keyup for this Windows key press? */ | ||
| 280 | int suppress_lone; /* Suppress simulated Windows keydown-keyup for this press? */ | ||
| 281 | int winseen; /* Windows keys seen during this press? */ | ||
| 282 | |||
| 283 | char alt_hooked[256]; /* hook Alt+[this key]? */ | ||
| 284 | char lwin_hooked[256]; /* hook left Win+[this key]? */ | ||
| 285 | char rwin_hooked[256]; /* hook right Win+[this key]? */ | ||
| 286 | } kbdhook; | ||
| 287 | typedef HWND (WINAPI *GetConsoleWindow_Proc) (void); | ||
| 288 | |||
| 289 | /* stdin, from w32console.c */ | ||
| 290 | extern HANDLE keyboard_handle; | ||
| 291 | |||
| 254 | /* Let the user specify a display with a frame. | 292 | /* Let the user specify a display with a frame. |
| 255 | nil stands for the selected frame--or, if that is not a w32 frame, | 293 | nil stands for the selected frame--or, if that is not a w32 frame, |
| 256 | the first display on the list. */ | 294 | the first display on the list. */ |
| @@ -2074,6 +2112,348 @@ my_post_msg (W32Msg * wmsg, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 2074 | post_msg (wmsg); | 2112 | post_msg (wmsg); |
| 2075 | } | 2113 | } |
| 2076 | 2114 | ||
| 2115 | /* The Windows keyboard hook callback. */ | ||
| 2116 | static LRESULT CALLBACK | ||
| 2117 | funhook (int code, WPARAM w, LPARAM l) | ||
| 2118 | { | ||
| 2119 | INPUT inputs[2]; | ||
| 2120 | HWND focus = GetFocus (); | ||
| 2121 | int console = 0; | ||
| 2122 | KBDLLHOOKSTRUCT const *hs = (KBDLLHOOKSTRUCT*)l; | ||
| 2123 | |||
| 2124 | if (code < 0 || (hs->flags & LLKHF_INJECTED)) | ||
| 2125 | return CallNextHookEx (0, code, w, l); | ||
| 2126 | |||
| 2127 | /* The keyboard hook sees keyboard input on all processes (except | ||
| 2128 | elevated ones, when Emacs itself is not elevated). As such, | ||
| 2129 | care must be taken to only filter out keyboard input when Emacs | ||
| 2130 | itself is on the foreground. | ||
| 2131 | |||
| 2132 | GetFocus returns a non-NULL window if another application is active, | ||
| 2133 | and always for a console Emacs process. For a console Emacs, determine | ||
| 2134 | focus by checking if the current foreground window is the process's | ||
| 2135 | console window. */ | ||
| 2136 | if (focus == NULL && kbdhook.console != NULL) | ||
| 2137 | { | ||
| 2138 | if (GetForegroundWindow () == kbdhook.console) | ||
| 2139 | { | ||
| 2140 | focus = kbdhook.console; | ||
| 2141 | console = 1; | ||
| 2142 | } | ||
| 2143 | } | ||
| 2144 | |||
| 2145 | /* First, check hooks for the left and right Windows keys. */ | ||
| 2146 | if (hs->vkCode == VK_LWIN || hs->vkCode == VK_RWIN) | ||
| 2147 | { | ||
| 2148 | if (focus != NULL && (w == WM_KEYDOWN || w == WM_SYSKEYDOWN)) | ||
| 2149 | { | ||
| 2150 | /* The key is being pressed in an Emacs window. */ | ||
| 2151 | if (hs->vkCode == VK_LWIN && !kbdhook.lwindown) | ||
| 2152 | { | ||
| 2153 | kbdhook.lwindown = 1; | ||
| 2154 | kbdhook.winseen = 1; | ||
| 2155 | kbdhook.winsdown++; | ||
| 2156 | } | ||
| 2157 | else if (hs->vkCode == VK_RWIN && !kbdhook.rwindown) | ||
| 2158 | { | ||
| 2159 | kbdhook.rwindown = 1; | ||
| 2160 | kbdhook.winseen = 1; | ||
| 2161 | kbdhook.winsdown++; | ||
| 2162 | } | ||
| 2163 | /* Returning 1 here drops the keypress without further processing. | ||
| 2164 | If the keypress was allowed to go through, the normal Windows | ||
| 2165 | hotkeys would take over. */ | ||
| 2166 | return 1; | ||
| 2167 | } | ||
| 2168 | else if (kbdhook.winsdown > 0 && (w == WM_KEYUP || w == WM_SYSKEYUP)) | ||
| 2169 | { | ||
| 2170 | /* A key that has been captured earlier is being released now. */ | ||
| 2171 | if (hs->vkCode == VK_LWIN && kbdhook.lwindown) | ||
| 2172 | { | ||
| 2173 | kbdhook.lwindown = 0; | ||
| 2174 | kbdhook.winsdown--; | ||
| 2175 | } | ||
| 2176 | else if (hs->vkCode == VK_RWIN && kbdhook.rwindown) | ||
| 2177 | { | ||
| 2178 | kbdhook.rwindown = 0; | ||
| 2179 | kbdhook.winsdown--; | ||
| 2180 | } | ||
| 2181 | if (kbdhook.winsdown == 0 && kbdhook.winseen) | ||
| 2182 | { | ||
| 2183 | if (!kbdhook.suppress_lone) | ||
| 2184 | { | ||
| 2185 | /* The Windows key was pressed, then released, | ||
| 2186 | without any other key pressed simultaneously. | ||
| 2187 | Normally, this opens the Start menu, but the user | ||
| 2188 | can prevent this by setting the | ||
| 2189 | w32-pass-[lr]window-to-system variable to | ||
| 2190 | NIL. */ | ||
| 2191 | if (hs->vkCode == VK_LWIN && !NILP (Vw32_pass_lwindow_to_system) || | ||
| 2192 | hs->vkCode == VK_RWIN && !NILP (Vw32_pass_rwindow_to_system)) | ||
| 2193 | { | ||
| 2194 | /* Not prevented - Simulate the keypress to the system. */ | ||
| 2195 | memset (inputs, 0, sizeof (inputs)); | ||
| 2196 | inputs[0].type = INPUT_KEYBOARD; | ||
| 2197 | inputs[0].ki.wVk = hs->vkCode; | ||
| 2198 | inputs[0].ki.wScan = hs->vkCode; | ||
| 2199 | inputs[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY; | ||
| 2200 | inputs[0].ki.time = 0; | ||
| 2201 | inputs[1].type = INPUT_KEYBOARD; | ||
| 2202 | inputs[1].ki.wVk = hs->vkCode; | ||
| 2203 | inputs[1].ki.wScan = hs->vkCode; | ||
| 2204 | inputs[1].ki.dwFlags | ||
| 2205 | = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP; | ||
| 2206 | inputs[1].ki.time = 0; | ||
| 2207 | SendInput (2, inputs, sizeof (INPUT)); | ||
| 2208 | } | ||
| 2209 | else if (focus != NULL) | ||
| 2210 | { | ||
| 2211 | /* When not passed to system, must simulate privately to Emacs. */ | ||
| 2212 | PostMessage (focus, WM_SYSKEYDOWN, hs->vkCode, 0); | ||
| 2213 | PostMessage (focus, WM_SYSKEYUP, hs->vkCode, 0); | ||
| 2214 | } | ||
| 2215 | } | ||
| 2216 | } | ||
| 2217 | if (kbdhook.winsdown == 0) | ||
| 2218 | { | ||
| 2219 | /* No Windows keys pressed anymore - clear the state flags. */ | ||
| 2220 | kbdhook.suppress_lone = 0; | ||
| 2221 | kbdhook.winseen = 0; | ||
| 2222 | } | ||
| 2223 | if (!kbdhook.send_win_up) | ||
| 2224 | { | ||
| 2225 | /* Swallow this release message, as not to confuse | ||
| 2226 | applications who did not get to see the original | ||
| 2227 | WM_KEYDOWN message either. */ | ||
| 2228 | return 1; | ||
| 2229 | } | ||
| 2230 | kbdhook.send_win_up = 0; | ||
| 2231 | } | ||
| 2232 | } | ||
| 2233 | else if (kbdhook.winsdown > 0) | ||
| 2234 | { | ||
| 2235 | /* Some other key was pressed while a captured Win key is down. | ||
| 2236 | This is either an Emacs registered hotkey combination, or a | ||
| 2237 | system hotkey. */ | ||
| 2238 | if (kbdhook.lwindown && kbdhook.lwin_hooked[hs->vkCode] || | ||
| 2239 | kbdhook.rwindown && kbdhook.rwin_hooked[hs->vkCode]) | ||
| 2240 | { | ||
| 2241 | /* Hooked Win-x combination, do not pass the keypress to Windows. */ | ||
| 2242 | kbdhook.suppress_lone = 1; | ||
| 2243 | } | ||
| 2244 | else if (!kbdhook.suppress_lone) | ||
| 2245 | { | ||
| 2246 | /* Unhooked S-x combination; simulate the combination now | ||
| 2247 | (will be seen by the system). */ | ||
| 2248 | memset (inputs, 0, sizeof (inputs)); | ||
| 2249 | inputs[0].type = INPUT_KEYBOARD; | ||
| 2250 | inputs[0].ki.wVk = kbdhook.lwindown ? VK_LWIN : VK_RWIN; | ||
| 2251 | inputs[0].ki.wScan = kbdhook.lwindown ? VK_LWIN : VK_RWIN; | ||
| 2252 | inputs[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY; | ||
| 2253 | inputs[0].ki.time = 0; | ||
| 2254 | inputs[1].type = INPUT_KEYBOARD; | ||
| 2255 | inputs[1].ki.wVk = hs->vkCode; | ||
| 2256 | inputs[1].ki.wScan = hs->scanCode; | ||
| 2257 | inputs[1].ki.dwFlags = | ||
| 2258 | (hs->flags & LLKHF_EXTENDED) ? KEYEVENTF_EXTENDEDKEY : 0; | ||
| 2259 | inputs[1].ki.time = 0; | ||
| 2260 | SendInput (2, inputs, sizeof (INPUT)); | ||
| 2261 | /* Stop processing of this Win sequence here; the | ||
| 2262 | corresponding keyup messages will come through the normal | ||
| 2263 | channel when the keys are released. */ | ||
| 2264 | kbdhook.suppress_lone = 1; | ||
| 2265 | kbdhook.send_win_up = 1; | ||
| 2266 | /* Swallow the original keypress (as we want the Win key | ||
| 2267 | down message simulated above to precede this real message). */ | ||
| 2268 | return 1; | ||
| 2269 | } | ||
| 2270 | } | ||
| 2271 | |||
| 2272 | /* Next, handle the registered Alt-* combinations. */ | ||
| 2273 | if ((w == WM_SYSKEYDOWN || w == WM_KEYDOWN) | ||
| 2274 | && kbdhook.alt_hooked[hs->vkCode] | ||
| 2275 | && focus != NULL | ||
| 2276 | && (GetAsyncKeyState (VK_MENU) & 0x8000)) | ||
| 2277 | { | ||
| 2278 | /* Prevent the system from getting this Alt-* key - suppress the | ||
| 2279 | message and post as a normal keypress to Emacs. */ | ||
| 2280 | if (console) | ||
| 2281 | { | ||
| 2282 | INPUT_RECORD rec; | ||
| 2283 | DWORD n; | ||
| 2284 | rec.EventType = KEY_EVENT; | ||
| 2285 | rec.Event.KeyEvent.bKeyDown = TRUE; | ||
| 2286 | rec.Event.KeyEvent.wVirtualKeyCode = hs->vkCode; | ||
| 2287 | rec.Event.KeyEvent.wVirtualScanCode = hs->scanCode; | ||
| 2288 | rec.Event.KeyEvent.uChar.UnicodeChar = 0; | ||
| 2289 | rec.Event.KeyEvent.dwControlKeyState = | ||
| 2290 | ((GetAsyncKeyState (VK_LMENU) & 0x8000) ? LEFT_ALT_PRESSED : 0) | ||
| 2291 | | ((GetAsyncKeyState (VK_RMENU) & 0x8000) ? RIGHT_ALT_PRESSED : 0) | ||
| 2292 | | ((GetAsyncKeyState (VK_LCONTROL) & 0x8000) ? LEFT_CTRL_PRESSED : 0) | ||
| 2293 | | ((GetAsyncKeyState (VK_RCONTROL) & 0x8000) ? RIGHT_CTRL_PRESSED : 0) | ||
| 2294 | | ((GetAsyncKeyState (VK_SHIFT) & 0x8000) ? SHIFT_PRESSED : 0) | ||
| 2295 | | ((hs->flags & LLKHF_EXTENDED) ? ENHANCED_KEY : 0); | ||
| 2296 | if (w32_console_unicode_input) | ||
| 2297 | WriteConsoleInputW (keyboard_handle, &rec, 1, &n); | ||
| 2298 | else | ||
| 2299 | WriteConsoleInputA (keyboard_handle, &rec, 1, &n); | ||
| 2300 | } | ||
| 2301 | else | ||
| 2302 | PostMessage (focus, w, hs->vkCode, 1 | (1<<29)); | ||
| 2303 | return 1; | ||
| 2304 | } | ||
| 2305 | |||
| 2306 | /* The normal case - pass the message through. */ | ||
| 2307 | return CallNextHookEx (0, code, w, l); | ||
| 2308 | } | ||
| 2309 | |||
| 2310 | /* Set up the hook; can be called several times, with matching | ||
| 2311 | remove_w32_kbdhook calls. */ | ||
| 2312 | void | ||
| 2313 | setup_w32_kbdhook (void) | ||
| 2314 | { | ||
| 2315 | kbdhook.hook_count++; | ||
| 2316 | |||
| 2317 | /* Hooking is only available on NT architecture systems, as | ||
| 2318 | indicated by the w32_kbdhook_active variable. */ | ||
| 2319 | if (kbdhook.hook_count == 1 && w32_kbdhook_active) | ||
| 2320 | { | ||
| 2321 | /* Get the handle of the Emacs console window. As the | ||
| 2322 | GetConsoleWindow function is only available on Win2000+, a | ||
| 2323 | hackish workaround described in Microsoft KB article 124103 | ||
| 2324 | (https://support.microsoft.com/en-us/kb/124103) is used for | ||
| 2325 | NT 4 systems. */ | ||
| 2326 | GetConsoleWindow_Proc get_console = (GetConsoleWindow_Proc) | ||
| 2327 | GetProcAddress (GetModuleHandle ("kernel32.dll"), "GetConsoleWindow"); | ||
| 2328 | |||
| 2329 | if (get_console != NULL) | ||
| 2330 | kbdhook.console = get_console (); | ||
| 2331 | else | ||
| 2332 | { | ||
| 2333 | GUID guid; | ||
| 2334 | wchar_t *oldTitle = malloc (1024 * sizeof(wchar_t)); | ||
| 2335 | wchar_t newTitle[64]; | ||
| 2336 | int i; | ||
| 2337 | |||
| 2338 | CoCreateGuid (&guid); | ||
| 2339 | StringFromGUID2 (&guid, newTitle, 64); | ||
| 2340 | if (newTitle != NULL) | ||
| 2341 | { | ||
| 2342 | GetConsoleTitleW (oldTitle, 1024); | ||
| 2343 | SetConsoleTitleW (newTitle); | ||
| 2344 | for (i = 0; i < 25; i++) | ||
| 2345 | { | ||
| 2346 | Sleep (40); | ||
| 2347 | kbdhook.console = FindWindowW (NULL, newTitle); | ||
| 2348 | if (kbdhook.console != NULL) | ||
| 2349 | break; | ||
| 2350 | } | ||
| 2351 | SetConsoleTitleW (oldTitle); | ||
| 2352 | } | ||
| 2353 | free (oldTitle); | ||
| 2354 | } | ||
| 2355 | |||
| 2356 | /* Set the hook. */ | ||
| 2357 | kbdhook.hook = SetWindowsHookEx (WH_KEYBOARD_LL, funhook, | ||
| 2358 | GetModuleHandle (NULL), 0); | ||
| 2359 | } | ||
| 2360 | } | ||
| 2361 | |||
| 2362 | /* Remove the hook. */ | ||
| 2363 | void | ||
| 2364 | remove_w32_kbdhook (void) | ||
| 2365 | { | ||
| 2366 | kbdhook.hook_count--; | ||
| 2367 | if (kbdhook.hook_count == 0 && w32_kbdhook_active) | ||
| 2368 | { | ||
| 2369 | UnhookWindowsHookEx (kbdhook.hook); | ||
| 2370 | kbdhook.hook = NULL; | ||
| 2371 | } | ||
| 2372 | } | ||
| 2373 | |||
| 2374 | /* Mark a specific key combination as hooked, preventing it to be | ||
| 2375 | handled by the system. */ | ||
| 2376 | void | ||
| 2377 | hook_w32_key (int hook, int modifier, int vkey) | ||
| 2378 | { | ||
| 2379 | char *tbl = NULL; | ||
| 2380 | |||
| 2381 | switch (modifier) | ||
| 2382 | { | ||
| 2383 | case VK_MENU: | ||
| 2384 | tbl = kbdhook.alt_hooked; | ||
| 2385 | break; | ||
| 2386 | case VK_LWIN: | ||
| 2387 | tbl = kbdhook.lwin_hooked; | ||
| 2388 | break; | ||
| 2389 | case VK_RWIN: | ||
| 2390 | tbl = kbdhook.rwin_hooked; | ||
| 2391 | break; | ||
| 2392 | } | ||
| 2393 | |||
| 2394 | if (tbl != NULL && vkey >= 0 && vkey <= 255) | ||
| 2395 | { | ||
| 2396 | /* VK_ANY hooks all keys for this modifier */ | ||
| 2397 | if (vkey == VK_ANY) | ||
| 2398 | memset (tbl, (char)hook, 256); | ||
| 2399 | else | ||
| 2400 | tbl[vkey] = (char)hook; | ||
| 2401 | /* Alt-<modifier>s should go through */ | ||
| 2402 | kbdhook.alt_hooked[VK_MENU] = 0; | ||
| 2403 | kbdhook.alt_hooked[VK_LMENU] = 0; | ||
| 2404 | kbdhook.alt_hooked[VK_RMENU] = 0; | ||
| 2405 | kbdhook.alt_hooked[VK_CONTROL] = 0; | ||
| 2406 | kbdhook.alt_hooked[VK_LCONTROL] = 0; | ||
| 2407 | kbdhook.alt_hooked[VK_RCONTROL] = 0; | ||
| 2408 | kbdhook.alt_hooked[VK_SHIFT] = 0; | ||
| 2409 | kbdhook.alt_hooked[VK_LSHIFT] = 0; | ||
| 2410 | kbdhook.alt_hooked[VK_RSHIFT] = 0; | ||
| 2411 | } | ||
| 2412 | } | ||
| 2413 | |||
| 2414 | /* Check the current Win key pressed state. */ | ||
| 2415 | int | ||
| 2416 | check_w32_winkey_state (int vkey) | ||
| 2417 | { | ||
| 2418 | /* The hook code handles grabbing of the Windows keys and Alt-* key | ||
| 2419 | combinations reserved by the system. Handling Alt is a bit | ||
| 2420 | easier, as Windows intends Alt-* shortcuts for application use in | ||
| 2421 | Windows; hotkeys such as Alt-tab and Alt-escape are special | ||
| 2422 | cases. Win-* hotkeys, on the other hand, are primarily meant for | ||
| 2423 | system use. | ||
| 2424 | |||
| 2425 | As a result, when we want Emacs to be able to grab the Win-* | ||
| 2426 | keys, we must swallow all Win key presses in a low-level keyboard | ||
| 2427 | hook. Unfortunately, this means that the Emacs window procedure | ||
| 2428 | (and console input handler) never see the keypresses either. | ||
| 2429 | Thus, to check the modifier states properly, Emacs code must use | ||
| 2430 | the check_w32_winkey_state function that uses the flags directly | ||
| 2431 | updated by the hook callback. */ | ||
| 2432 | switch (vkey) | ||
| 2433 | { | ||
| 2434 | case VK_LWIN: | ||
| 2435 | return kbdhook.lwindown; | ||
| 2436 | case VK_RWIN: | ||
| 2437 | return kbdhook.rwindown; | ||
| 2438 | } | ||
| 2439 | return 0; | ||
| 2440 | } | ||
| 2441 | |||
| 2442 | /* Reset the keyboard hook state. Locking the workstation with Win-L | ||
| 2443 | leaves the Win key(s) "down" from the hook's point of view - the | ||
| 2444 | keyup event is never seen. Thus, this function must be called when | ||
| 2445 | the system is locked. */ | ||
| 2446 | void | ||
| 2447 | reset_w32_kbdhook_state (void) | ||
| 2448 | { | ||
| 2449 | kbdhook.lwindown = 0; | ||
| 2450 | kbdhook.rwindown = 0; | ||
| 2451 | kbdhook.winsdown = 0; | ||
| 2452 | kbdhook.send_win_up = 0; | ||
| 2453 | kbdhook.suppress_lone = 0; | ||
| 2454 | kbdhook.winseen = 0; | ||
| 2455 | } | ||
| 2456 | |||
| 2077 | /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish | 2457 | /* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish |
| 2078 | between left and right keys as advertised. We test for this | 2458 | between left and right keys as advertised. We test for this |
| 2079 | support dynamically, and set a flag when the support is absent. If | 2459 | support dynamically, and set a flag when the support is absent. If |
| @@ -2248,6 +2628,8 @@ modifier_set (int vkey) | |||
| 2248 | else | 2628 | else |
| 2249 | return (GetKeyState (vkey) & 0x1); | 2629 | return (GetKeyState (vkey) & 0x1); |
| 2250 | } | 2630 | } |
| 2631 | if (w32_kbdhook_active && (vkey == VK_LWIN || vkey == VK_RWIN)) | ||
| 2632 | return check_w32_winkey_state (vkey); | ||
| 2251 | 2633 | ||
| 2252 | if (!modifiers_recorded) | 2634 | if (!modifiers_recorded) |
| 2253 | return (GetKeyState (vkey) & 0x8000); | 2635 | return (GetKeyState (vkey) & 0x8000); |
| @@ -2390,7 +2772,9 @@ map_keypad_keys (unsigned int virt_key, unsigned int extended) | |||
| 2390 | /* List of special key combinations which w32 would normally capture, | 2772 | /* List of special key combinations which w32 would normally capture, |
| 2391 | but Emacs should grab instead. Not directly visible to lisp, to | 2773 | but Emacs should grab instead. Not directly visible to lisp, to |
| 2392 | simplify synchronization. Each item is an integer encoding a virtual | 2774 | simplify synchronization. Each item is an integer encoding a virtual |
| 2393 | key code and modifier combination to capture. */ | 2775 | key code and modifier combination to capture. |
| 2776 | Note: This code is not used if keyboard hooks are active | ||
| 2777 | (Windows 2000 and later). */ | ||
| 2394 | static Lisp_Object w32_grabbed_keys; | 2778 | static Lisp_Object w32_grabbed_keys; |
| 2395 | 2779 | ||
| 2396 | #define HOTKEY(vk, mods) make_number (((vk) & 255) | ((mods) << 8)) | 2780 | #define HOTKEY(vk, mods) make_number (((vk) & 255) | ((mods) << 8)) |
| @@ -3440,7 +3824,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3440 | switch (wParam) | 3824 | switch (wParam) |
| 3441 | { | 3825 | { |
| 3442 | case VK_LWIN: | 3826 | case VK_LWIN: |
| 3443 | if (NILP (Vw32_pass_lwindow_to_system)) | 3827 | if (!w32_kbdhook_active && NILP (Vw32_pass_lwindow_to_system)) |
| 3444 | { | 3828 | { |
| 3445 | /* Prevent system from acting on keyup (which opens the | 3829 | /* Prevent system from acting on keyup (which opens the |
| 3446 | Start menu if no other key was pressed) by simulating a | 3830 | Start menu if no other key was pressed) by simulating a |
| @@ -3459,7 +3843,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 3459 | return 0; | 3843 | return 0; |
| 3460 | break; | 3844 | break; |
| 3461 | case VK_RWIN: | 3845 | case VK_RWIN: |
| 3462 | if (NILP (Vw32_pass_rwindow_to_system)) | 3846 | if (!w32_kbdhook_active && NILP (Vw32_pass_rwindow_to_system)) |
| 3463 | { | 3847 | { |
| 3464 | if (GetAsyncKeyState (wParam) & 1) | 3848 | if (GetAsyncKeyState (wParam) & 1) |
| 3465 | { | 3849 | { |
| @@ -4316,10 +4700,12 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 4316 | case WM_SETFOCUS: | 4700 | case WM_SETFOCUS: |
| 4317 | dpyinfo->faked_key = 0; | 4701 | dpyinfo->faked_key = 0; |
| 4318 | reset_modifiers (); | 4702 | reset_modifiers (); |
| 4319 | register_hot_keys (hwnd); | 4703 | if (!w32_kbdhook_active) |
| 4704 | register_hot_keys (hwnd); | ||
| 4320 | goto command; | 4705 | goto command; |
| 4321 | case WM_KILLFOCUS: | 4706 | case WM_KILLFOCUS: |
| 4322 | unregister_hot_keys (hwnd); | 4707 | if (!w32_kbdhook_active) |
| 4708 | unregister_hot_keys (hwnd); | ||
| 4323 | button_state = 0; | 4709 | button_state = 0; |
| 4324 | ReleaseCapture (); | 4710 | ReleaseCapture (); |
| 4325 | /* Relinquish the system caret. */ | 4711 | /* Relinquish the system caret. */ |
| @@ -4348,10 +4734,20 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) | |||
| 4348 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | 4734 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); |
| 4349 | goto dflt; | 4735 | goto dflt; |
| 4350 | 4736 | ||
| 4737 | case WM_CREATE: | ||
| 4738 | setup_w32_kbdhook (); | ||
| 4739 | goto dflt; | ||
| 4740 | |||
| 4351 | case WM_DESTROY: | 4741 | case WM_DESTROY: |
| 4742 | remove_w32_kbdhook (); | ||
| 4352 | CoUninitialize (); | 4743 | CoUninitialize (); |
| 4353 | return 0; | 4744 | return 0; |
| 4354 | 4745 | ||
| 4746 | case WM_WTSSESSION_CHANGE: | ||
| 4747 | if (wParam == WTS_SESSION_LOCK) | ||
| 4748 | reset_w32_kbdhook_state (); | ||
| 4749 | goto dflt; | ||
| 4750 | |||
| 4355 | case WM_CLOSE: | 4751 | case WM_CLOSE: |
| 4356 | wmsg.dwModifiers = w32_get_modifiers (); | 4752 | wmsg.dwModifiers = w32_get_modifiers (); |
| 4357 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | 4753 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); |
| @@ -7617,19 +8013,34 @@ lookup_vk_code (char *key) | |||
| 7617 | && strcmp (lispy_function_keys[i], key) == 0) | 8013 | && strcmp (lispy_function_keys[i], key) == 0) |
| 7618 | return i; | 8014 | return i; |
| 7619 | 8015 | ||
| 8016 | if (w32_kbdhook_active) | ||
| 8017 | { | ||
| 8018 | /* Alphanumerics map to themselves. */ | ||
| 8019 | if (key[1] == 0) | ||
| 8020 | { | ||
| 8021 | if (key[0] >= 'A' && key[0] <= 'Z' || | ||
| 8022 | key[0] >= '0' && key[0] <= '9') | ||
| 8023 | return key[0]; | ||
| 8024 | if (key[0] >= 'a' && key[0] <= 'z') | ||
| 8025 | return toupper(key[0]); | ||
| 8026 | } | ||
| 8027 | } | ||
| 8028 | |||
| 7620 | return -1; | 8029 | return -1; |
| 7621 | } | 8030 | } |
| 7622 | 8031 | ||
| 7623 | /* Convert a one-element vector style key sequence to a hot key | 8032 | /* Convert a one-element vector style key sequence to a hot key |
| 7624 | definition. */ | 8033 | definition. */ |
| 7625 | static Lisp_Object | 8034 | static Lisp_Object |
| 7626 | w32_parse_hot_key (Lisp_Object key) | 8035 | w32_parse_and_hook_hot_key (Lisp_Object key, int hook) |
| 7627 | { | 8036 | { |
| 7628 | /* Copied from Fdefine_key and store_in_keymap. */ | 8037 | /* Copied from Fdefine_key and store_in_keymap. */ |
| 7629 | register Lisp_Object c; | 8038 | register Lisp_Object c; |
| 7630 | int vk_code; | 8039 | int vk_code; |
| 7631 | int lisp_modifiers; | 8040 | int lisp_modifiers; |
| 7632 | int w32_modifiers; | 8041 | int w32_modifiers; |
| 8042 | Lisp_Object res = Qnil; | ||
| 8043 | char* vkname; | ||
| 7633 | 8044 | ||
| 7634 | CHECK_VECTOR (key); | 8045 | CHECK_VECTOR (key); |
| 7635 | 8046 | ||
| @@ -7652,7 +8063,12 @@ w32_parse_hot_key (Lisp_Object key) | |||
| 7652 | c = Fcar (c); | 8063 | c = Fcar (c); |
| 7653 | if (!SYMBOLP (c)) | 8064 | if (!SYMBOLP (c)) |
| 7654 | emacs_abort (); | 8065 | emacs_abort (); |
| 7655 | vk_code = lookup_vk_code (SSDATA (SYMBOL_NAME (c))); | 8066 | vkname = SSDATA (SYMBOL_NAME (c)); |
| 8067 | /* [s-], [M-], [h-]: Register all keys for this modifier */ | ||
| 8068 | if (w32_kbdhook_active && vkname[0] == 0) | ||
| 8069 | vk_code = VK_ANY; | ||
| 8070 | else | ||
| 8071 | vk_code = lookup_vk_code (vkname); | ||
| 7656 | } | 8072 | } |
| 7657 | else if (INTEGERP (c)) | 8073 | else if (INTEGERP (c)) |
| 7658 | { | 8074 | { |
| @@ -7676,34 +8092,75 @@ w32_parse_hot_key (Lisp_Object key) | |||
| 7676 | #define MOD_WIN 0x0008 | 8092 | #define MOD_WIN 0x0008 |
| 7677 | #endif | 8093 | #endif |
| 7678 | 8094 | ||
| 7679 | /* Convert lisp modifiers to Windows hot-key form. */ | 8095 | if (w32_kbdhook_active) |
| 7680 | w32_modifiers = (lisp_modifiers & hyper_modifier) ? MOD_WIN : 0; | 8096 | { |
| 7681 | w32_modifiers |= (lisp_modifiers & alt_modifier) ? MOD_ALT : 0; | 8097 | /* Register Alt-x combinations. */ |
| 7682 | w32_modifiers |= (lisp_modifiers & ctrl_modifier) ? MOD_CONTROL : 0; | 8098 | if (lisp_modifiers & alt_modifier) |
| 7683 | w32_modifiers |= (lisp_modifiers & shift_modifier) ? MOD_SHIFT : 0; | 8099 | { |
| 8100 | hook_w32_key (hook, VK_MENU, vk_code); | ||
| 8101 | res = Qt; | ||
| 8102 | } | ||
| 8103 | /* Register Win-x combinations based on modifier mappings. */ | ||
| 8104 | if (((lisp_modifiers & hyper_modifier) | ||
| 8105 | && EQ (Vw32_lwindow_modifier, Qhyper)) | ||
| 8106 | || ((lisp_modifiers & super_modifier) | ||
| 8107 | && EQ (Vw32_lwindow_modifier, Qsuper))) | ||
| 8108 | { | ||
| 8109 | hook_w32_key (hook, VK_LWIN, vk_code); | ||
| 8110 | res = Qt; | ||
| 8111 | } | ||
| 8112 | if (((lisp_modifiers & hyper_modifier) | ||
| 8113 | && EQ (Vw32_rwindow_modifier, Qhyper)) | ||
| 8114 | || ((lisp_modifiers & super_modifier) | ||
| 8115 | && EQ (Vw32_rwindow_modifier, Qsuper))) | ||
| 8116 | { | ||
| 8117 | hook_w32_key (hook, VK_RWIN, vk_code); | ||
| 8118 | res = Qt; | ||
| 8119 | } | ||
| 8120 | return res; | ||
| 8121 | } | ||
| 8122 | else | ||
| 8123 | { | ||
| 8124 | /* Convert lisp modifiers to Windows hot-key form. */ | ||
| 8125 | w32_modifiers = (lisp_modifiers & hyper_modifier) ? MOD_WIN : 0; | ||
| 8126 | w32_modifiers |= (lisp_modifiers & alt_modifier) ? MOD_ALT : 0; | ||
| 8127 | w32_modifiers |= (lisp_modifiers & ctrl_modifier) ? MOD_CONTROL : 0; | ||
| 8128 | w32_modifiers |= (lisp_modifiers & shift_modifier) ? MOD_SHIFT : 0; | ||
| 7684 | 8129 | ||
| 7685 | return HOTKEY (vk_code, w32_modifiers); | 8130 | return HOTKEY (vk_code, w32_modifiers); |
| 8131 | } | ||
| 7686 | } | 8132 | } |
| 7687 | 8133 | ||
| 7688 | DEFUN ("w32-register-hot-key", Fw32_register_hot_key, | 8134 | DEFUN ("w32-register-hot-key", Fw32_register_hot_key, |
| 7689 | Sw32_register_hot_key, 1, 1, 0, | 8135 | Sw32_register_hot_key, 1, 1, 0, |
| 7690 | doc: /* Register KEY as a hot-key combination. | 8136 | doc: /* Register KEY as a hot-key combination. |
| 7691 | Certain key combinations like Alt-Tab are reserved for system use on | 8137 | Certain key combinations like Alt-Tab and Win-R are reserved for |
| 7692 | Windows, and therefore are normally intercepted by the system. However, | 8138 | system use on Windows, and therefore are normally intercepted by the |
| 7693 | most of these key combinations can be received by registering them as | 8139 | system. These key combinations can be received by registering them |
| 7694 | hot-keys, overriding their special meaning. | 8140 | as hot-keys, except for Win-L which always locks the computer. |
| 7695 | 8141 | ||
| 7696 | KEY must be a one element key definition in vector form that would be | 8142 | On Windows 98 and ME, KEY must be a one element key definition in |
| 7697 | acceptable to `define-key' (e.g. [A-tab] for Alt-Tab). The meta | 8143 | vector form that would be acceptable to `define-key' (e.g. [A-tab] for |
| 7698 | modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper | 8144 | Alt-Tab). The meta modifier is interpreted as Alt if |
| 7699 | is always interpreted as the Windows modifier keys. | 8145 | `w32-alt-is-meta' is t, and hyper is always interpreted as the Windows |
| 7700 | 8146 | modifier keys. The return value is the hotkey-id if registered, otherwise nil. | |
| 7701 | The return value is the hotkey-id if registered, otherwise nil. */) | 8147 | |
| 8148 | On Windows versions since NT, KEY can also be specified as [M-], [s-] or | ||
| 8149 | [h-] to indicate that all combinations of that key should be processed | ||
| 8150 | by Emacs instead of the operating system. The super and hyper | ||
| 8151 | modifiers are interpreted according to the current values of | ||
| 8152 | `w32-lwindow-modifier' and `w32-rwindow-modifier'. For instance, | ||
| 8153 | setting `w32-lwindow-modifier' to `super' and then calling | ||
| 8154 | `(register-hot-key [s-])' grabs all combinations of the left Windows | ||
| 8155 | key to Emacs, but leaves the right Windows key free for the operating | ||
| 8156 | system keyboard shortcuts. The return value is t if the call affected | ||
| 8157 | any key combinations, otherwise nil. */) | ||
| 7702 | (Lisp_Object key) | 8158 | (Lisp_Object key) |
| 7703 | { | 8159 | { |
| 7704 | key = w32_parse_hot_key (key); | 8160 | key = w32_parse_and_hook_hot_key (key, 1); |
| 7705 | 8161 | ||
| 7706 | if (!NILP (key) && NILP (Fmemq (key, w32_grabbed_keys))) | 8162 | if (!w32_kbdhook_active |
| 8163 | && !NILP (key) && NILP (Fmemq (key, w32_grabbed_keys))) | ||
| 7707 | { | 8164 | { |
| 7708 | /* Reuse an empty slot if possible. */ | 8165 | /* Reuse an empty slot if possible. */ |
| 7709 | Lisp_Object item = Fmemq (Qnil, w32_grabbed_keys); | 8166 | Lisp_Object item = Fmemq (Qnil, w32_grabbed_keys); |
| @@ -7731,7 +8188,10 @@ DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key, | |||
| 7731 | Lisp_Object item; | 8188 | Lisp_Object item; |
| 7732 | 8189 | ||
| 7733 | if (!INTEGERP (key)) | 8190 | if (!INTEGERP (key)) |
| 7734 | key = w32_parse_hot_key (key); | 8191 | key = w32_parse_and_hook_hot_key (key, 0); |
| 8192 | |||
| 8193 | if (w32_kbdhook_active) | ||
| 8194 | return key; | ||
| 7735 | 8195 | ||
| 7736 | item = Fmemq (key, w32_grabbed_keys); | 8196 | item = Fmemq (key, w32_grabbed_keys); |
| 7737 | 8197 | ||
| @@ -9338,11 +9798,15 @@ When non-nil, the Start menu is opened by tapping the key. | |||
| 9338 | If you set this to nil, the left \"Windows\" key is processed by Emacs | 9798 | If you set this to nil, the left \"Windows\" key is processed by Emacs |
| 9339 | according to the value of `w32-lwindow-modifier', which see. | 9799 | according to the value of `w32-lwindow-modifier', which see. |
| 9340 | 9800 | ||
| 9341 | Note that some combinations of the left \"Windows\" key with other keys are | 9801 | Note that some combinations of the left \"Windows\" key with other |
| 9342 | caught by Windows at low level, and so binding them in Emacs will have no | 9802 | keys are caught by Windows at low level. For example, <lwindow>-r |
| 9343 | effect. For example, <lwindow>-r always pops up the Windows Run dialog, | 9803 | pops up the Windows Run dialog, <lwindow>-<Pause> pops up the "System |
| 9344 | <lwindow>-<Pause> pops up the "System Properties" dialog, etc. However, see | 9804 | Properties" dialog, etc. On Windows 10, no \"Windows\" key |
| 9345 | the doc string of `w32-phantom-key-code'. */); | 9805 | combinations are normally handed to applications. To enable Emacs to |
| 9806 | process \"Windows\" key combinations, use the function | ||
| 9807 | `w32-register-hot-key`. | ||
| 9808 | |||
| 9809 | For Windows 98/ME, see the doc string of `w32-phantom-key-code'. */); | ||
| 9346 | Vw32_pass_lwindow_to_system = Qt; | 9810 | Vw32_pass_lwindow_to_system = Qt; |
| 9347 | 9811 | ||
| 9348 | DEFVAR_LISP ("w32-pass-rwindow-to-system", | 9812 | DEFVAR_LISP ("w32-pass-rwindow-to-system", |
| @@ -9353,11 +9817,15 @@ When non-nil, the Start menu is opened by tapping the key. | |||
| 9353 | If you set this to nil, the right \"Windows\" key is processed by Emacs | 9817 | If you set this to nil, the right \"Windows\" key is processed by Emacs |
| 9354 | according to the value of `w32-rwindow-modifier', which see. | 9818 | according to the value of `w32-rwindow-modifier', which see. |
| 9355 | 9819 | ||
| 9356 | Note that some combinations of the right \"Windows\" key with other keys are | 9820 | Note that some combinations of the right \"Windows\" key with other |
| 9357 | caught by Windows at low level, and so binding them in Emacs will have no | 9821 | keys are caught by Windows at low level. For example, <rwindow>-r |
| 9358 | effect. For example, <rwindow>-r always pops up the Windows Run dialog, | 9822 | pops up the Windows Run dialog, <rwindow>-<Pause> pops up the "System |
| 9359 | <rwindow>-<Pause> pops up the "System Properties" dialog, etc. However, see | 9823 | Properties" dialog, etc. On Windows 10, no \"Windows\" key |
| 9360 | the doc string of `w32-phantom-key-code'. */); | 9824 | combinations are normally handed to applications. To enable Emacs to |
| 9825 | process \"Windows\" key combinations, use the function | ||
| 9826 | `w32-register-hot-key`. | ||
| 9827 | |||
| 9828 | For Windows 98/ME, see the doc string of `w32-phantom-key-code'. */); | ||
| 9361 | Vw32_pass_rwindow_to_system = Qt; | 9829 | Vw32_pass_rwindow_to_system = Qt; |
| 9362 | 9830 | ||
| 9363 | DEFVAR_LISP ("w32-phantom-key-code", | 9831 | DEFVAR_LISP ("w32-phantom-key-code", |
| @@ -9367,7 +9835,11 @@ Value is a number between 0 and 255. | |||
| 9367 | 9835 | ||
| 9368 | Phantom key presses are generated in order to stop the system from | 9836 | Phantom key presses are generated in order to stop the system from |
| 9369 | acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or | 9837 | acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or |
| 9370 | `w32-pass-rwindow-to-system' is nil. */); | 9838 | `w32-pass-rwindow-to-system' is nil. |
| 9839 | |||
| 9840 | This variable is only used on Windows 98 and ME. For other Windows | ||
| 9841 | versions, see the documentation of the `w32-register-hot-key` | ||
| 9842 | function. */); | ||
| 9371 | /* Although 255 is technically not a valid key code, it works and | 9843 | /* Although 255 is technically not a valid key code, it works and |
| 9372 | means that this hack won't interfere with any real key code. */ | 9844 | means that this hack won't interfere with any real key code. */ |
| 9373 | XSETINT (Vw32_phantom_key_code, 255); | 9845 | XSETINT (Vw32_phantom_key_code, 255); |
| @@ -9397,7 +9869,9 @@ Any other value will cause the Scroll Lock key to be ignored. */); | |||
| 9397 | doc: /* Modifier to use for the left \"Windows\" key. | 9869 | doc: /* Modifier to use for the left \"Windows\" key. |
| 9398 | The value can be hyper, super, meta, alt, control or shift for the | 9870 | The value can be hyper, super, meta, alt, control or shift for the |
| 9399 | respective modifier, or nil to appear as the `lwindow' key. | 9871 | respective modifier, or nil to appear as the `lwindow' key. |
| 9400 | Any other value will cause the key to be ignored. */); | 9872 | Any other value will cause the key to be ignored. |
| 9873 | |||
| 9874 | Also see the documentation of the `w32-register-hot-key` function. */); | ||
| 9401 | Vw32_lwindow_modifier = Qnil; | 9875 | Vw32_lwindow_modifier = Qnil; |
| 9402 | 9876 | ||
| 9403 | DEFVAR_LISP ("w32-rwindow-modifier", | 9877 | DEFVAR_LISP ("w32-rwindow-modifier", |
| @@ -9405,7 +9879,9 @@ Any other value will cause the key to be ignored. */); | |||
| 9405 | doc: /* Modifier to use for the right \"Windows\" key. | 9879 | doc: /* Modifier to use for the right \"Windows\" key. |
| 9406 | The value can be hyper, super, meta, alt, control or shift for the | 9880 | The value can be hyper, super, meta, alt, control or shift for the |
| 9407 | respective modifier, or nil to appear as the `rwindow' key. | 9881 | respective modifier, or nil to appear as the `rwindow' key. |
| 9408 | Any other value will cause the key to be ignored. */); | 9882 | Any other value will cause the key to be ignored. |
| 9883 | |||
| 9884 | Also see the documentation of the `w32-register-hot-key` function. */); | ||
| 9409 | Vw32_rwindow_modifier = Qnil; | 9885 | Vw32_rwindow_modifier = Qnil; |
| 9410 | 9886 | ||
| 9411 | DEFVAR_LISP ("w32-apps-modifier", | 9887 | DEFVAR_LISP ("w32-apps-modifier", |
diff --git a/src/w32inevt.c b/src/w32inevt.c index e714e27f4bc..c7246c7a8e2 100644 --- a/src/w32inevt.c +++ b/src/w32inevt.c | |||
| @@ -41,6 +41,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 41 | #include "termchar.h" /* for Mouse_HLInfo, tty_display_info */ | 41 | #include "termchar.h" /* for Mouse_HLInfo, tty_display_info */ |
| 42 | #include "w32term.h" | 42 | #include "w32term.h" |
| 43 | #include "w32inevt.h" | 43 | #include "w32inevt.h" |
| 44 | #include "w32common.h" | ||
| 44 | 45 | ||
| 45 | /* stdin, from w32console.c */ | 46 | /* stdin, from w32console.c */ |
| 46 | extern HANDLE keyboard_handle; | 47 | extern HANDLE keyboard_handle; |
| @@ -148,10 +149,12 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead) | |||
| 148 | switch (event->wVirtualKeyCode) | 149 | switch (event->wVirtualKeyCode) |
| 149 | { | 150 | { |
| 150 | case VK_LWIN: | 151 | case VK_LWIN: |
| 151 | mod_key_state &= ~LEFT_WIN_PRESSED; | 152 | if (!w32_kbdhook_active) |
| 153 | mod_key_state &= ~LEFT_WIN_PRESSED; | ||
| 152 | break; | 154 | break; |
| 153 | case VK_RWIN: | 155 | case VK_RWIN: |
| 154 | mod_key_state &= ~RIGHT_WIN_PRESSED; | 156 | if (!w32_kbdhook_active) |
| 157 | mod_key_state &= ~RIGHT_WIN_PRESSED; | ||
| 155 | break; | 158 | break; |
| 156 | case VK_APPS: | 159 | case VK_APPS: |
| 157 | mod_key_state &= ~APPS_PRESSED; | 160 | mod_key_state &= ~APPS_PRESSED; |
| @@ -185,7 +188,8 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead) | |||
| 185 | keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0); | 188 | keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0); |
| 186 | } | 189 | } |
| 187 | } | 190 | } |
| 188 | mod_key_state |= LEFT_WIN_PRESSED; | 191 | if (!w32_kbdhook_active) |
| 192 | mod_key_state |= LEFT_WIN_PRESSED; | ||
| 189 | if (!NILP (Vw32_lwindow_modifier)) | 193 | if (!NILP (Vw32_lwindow_modifier)) |
| 190 | return 0; | 194 | return 0; |
| 191 | break; | 195 | break; |
| @@ -201,7 +205,8 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead) | |||
| 201 | keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0); | 205 | keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0); |
| 202 | } | 206 | } |
| 203 | } | 207 | } |
| 204 | mod_key_state |= RIGHT_WIN_PRESSED; | 208 | if (!w32_kbdhook_active) |
| 209 | mod_key_state |= RIGHT_WIN_PRESSED; | ||
| 205 | if (!NILP (Vw32_rwindow_modifier)) | 210 | if (!NILP (Vw32_rwindow_modifier)) |
| 206 | return 0; | 211 | return 0; |
| 207 | break; | 212 | break; |
| @@ -267,6 +272,13 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead) | |||
| 267 | 272 | ||
| 268 | /* Recognize state of Windows and Apps keys. */ | 273 | /* Recognize state of Windows and Apps keys. */ |
| 269 | event->dwControlKeyState |= mod_key_state; | 274 | event->dwControlKeyState |= mod_key_state; |
| 275 | if (w32_kbdhook_active) | ||
| 276 | { | ||
| 277 | if (check_w32_winkey_state (VK_LWIN)) | ||
| 278 | event->dwControlKeyState |= LEFT_WIN_PRESSED; | ||
| 279 | if (check_w32_winkey_state (VK_RWIN)) | ||
| 280 | event->dwControlKeyState |= RIGHT_WIN_PRESSED; | ||
| 281 | } | ||
| 270 | 282 | ||
| 271 | /* Distinguish numeric keypad keys from extended keys. */ | 283 | /* Distinguish numeric keypad keys from extended keys. */ |
| 272 | event->wVirtualKeyCode = | 284 | event->wVirtualKeyCode = |
diff --git a/src/w32term.h b/src/w32term.h index 50906241f98..aed89d8c254 100644 --- a/src/w32term.h +++ b/src/w32term.h | |||
| @@ -738,6 +738,12 @@ extern int handle_file_notifications (struct input_event *); | |||
| 738 | extern void w32_initialize_display_info (Lisp_Object); | 738 | extern void w32_initialize_display_info (Lisp_Object); |
| 739 | extern void initialize_w32_display (struct terminal *, int *, int *); | 739 | extern void initialize_w32_display (struct terminal *, int *, int *); |
| 740 | 740 | ||
| 741 | /* Keyboard hooks. */ | ||
| 742 | extern void setup_w32_kbdhook (void); | ||
| 743 | extern void remove_w32_kbdhook (void); | ||
| 744 | extern int check_w32_winkey_state (int); | ||
| 745 | #define w32_kbdhook_active (os_subtype != OS_9X) | ||
| 746 | |||
| 741 | /* Keypad command key support. W32 doesn't have virtual keys defined | 747 | /* Keypad command key support. W32 doesn't have virtual keys defined |
| 742 | for the function keys on the keypad (they are mapped to the standard | 748 | for the function keys on the keypad (they are mapped to the standard |
| 743 | function keys), so we define our own. */ | 749 | function keys), so we define our own. */ |