Commit 97d7a0b8 authored by Jussi Lahdenniemi's avatar Jussi Lahdenniemi Committed by Eli Zaretskii

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.
parent 22994735
......@@ -507,32 +507,64 @@ the variable @code{w32-alt-is-meta} to a @code{nil} value.
@findex w32-register-hot-key
@findex w32-unregister-hot-key
MS-Windows reserves certain key combinations, such as
@kbd{@key{Alt}-@key{TAB}}, for its own use. These key combinations are
intercepted by the system before Emacs can see them. You can use the
@code{w32-register-hot-key} function to allow a key sequence to be
seen by Emacs instead of being grabbed by Windows. This function
registers a key sequence as a @dfn{hot key}, overriding the special
meaning of that key sequence for Windows. (MS-Windows is told that
the key sequence is a hot key only when one of the Emacs windows has
focus, so that the special keys still have their usual meaning for
other Windows applications.)
The argument to @code{w32-register-hot-key} must be a single key,
with or without modifiers, in vector form that would be acceptable to
@code{define-key}. The meta modifier is interpreted as the @key{Alt}
key if @code{w32-alt-is-meta} is @code{t} (the default), and the hyper
modifier is always interpreted as the Windows key (usually labeled
with @key{start} and the Windows logo). If the function succeeds in
registering the key sequence, it returns the hotkey ID, a number;
otherwise it returns @code{nil}.
@kbd{@key{Alt}-@key{TAB}} and a number of Windows key combinations,
for its own use. These key combinations are intercepted by the system
before Emacs can see them. Also, on Windows 10, all Windows key
combinations are reserved by the system in such a way that they are
never propagated to applications, even if the system does not
currently define a hotkey on the specific combination. You can use
the @code{w32-register-hot-key} function to allow a key sequence to be
seen by Emacs instead of being grabbed by Windows. When registered as
a hot key, the key combination is pulled out of the system's input
queue before it is handled by Windows, effectively overriding the
special meaning of that key sequence for Windows. The override is
only effective when Emacs is active; with other applications on the
foreground the keys behave normally.
The argument to @code{w32-register-hot-key} must be a single key with a
single modifier, in vector form that would be acceptable to
@code{define-key}. The control and shift modifiers have no effect on the
argument. The meta modifier is interpreted as the @key{Alt} key if
@code{w32-alt-is-meta} is @code{t} (the default), and the super and hyper
modifiers are interpreted according to the bindings of
@code{w32-lwindow-modifier} and @code{w32-rwindow-modifier}. Additionally, a
modifier with the trailing dash but with no key indicates that all
Windows defined hotkeys for that modifier are to be overridden in the
favor of Emacs.
@kindex M-TAB@r{, (MS-Windows)}
@cindex @kbd{M-@key{TAB}} vs @kbd{@key{Alt}-@key{TAB}} (MS-Windows)
@cindex @kbd{@key{Alt}-@key{TAB}} vs @kbd{M-@key{TAB}} (MS-Windows)
For example, @code{(w32-register-hot-key [M-tab])} lets you use
@kbd{M-@key{TAB}} normally in Emacs; for instance, to complete the word or
symbol at point at top level, or to complete the current search string
against previously sought strings during incremental search.
@kbd{M-@key{TAB}} normally in Emacs; for instance, to complete the
word or symbol at point at top level, or to complete the current
search string against previously sought strings during incremental
search. @code{(w32-register-hot-key [s-])} with
@code{w32-lwindow-modifier} bound to @code{super} disables all the
Windows' own Windows key based shortcuts.@footnote{There is one known
exception: The combination @kbd{@key{Windows}-@key{L}} that locks the
workstation is handled by the system on a lower level. For this
reason, @code{w32-register-hot-key} cannot override this key
combination - it always locks the computer.}
Note that @code{w32-register-hot-key} checks the
@code{w32-[lr]window-modifier} values at the time of the function
call. Thus, you can set @code{w32-lwindow-modifier} as @code{super},
then call @code{(w32-register-hot-key [s-r])}, and finally set
@code{w32-rwindow-modifier} as @code{super} as well. The result is
that the left Windows key together with @key{R} invokes whichever
function you have bound for the combination in Emacs, and the right
Windows key and @key{R} opens the Windows @code{Run} dialog.
The hotkey registrations always also include all the shift and
control modifier combinations for the given hotkey; that is,
registering @kbd{s-@key{a}} as a hotkey gives you @kbd{S-s-@key{a}},
@kbd{C-s-@key{a}} and @kbd{C-S-s-@key{a}} as well.
On Windows 98 and ME, the hotkey registration is more restricted.
The desired hotkey must always be fully specified, and
@code{w32-phantom-key-code} can be customized to achieve desired
results.
The function @code{w32-unregister-hot-key} reverses the effect of
@code{w32-register-hot-key} for its argument key sequence.
......@@ -607,12 +639,7 @@ keys are passed to Windows or swallowed by Emacs. If the value is
otherwise it is passed to Windows. The default is @code{t} for both
of these variables. Passing each of these keys to Windows produces
its normal effect: for example, @kbd{@key{Lwindow}} opens the
@code{Start} menu, etc.@footnote{
Some combinations of the ``Windows'' keys with other keys are caught
by Windows at a low level in a way that Emacs currently cannot prevent.
For example, @kbd{@key{Lwindow} r} always pops up the Windows
@samp{Run} dialog. Customizing the value of
@code{w32-phantom-key-code} might help in some cases, though.}
@code{Start} menu, etc.
@vindex w32-recognize-altgr
@kindex AltGr @r{(MS-Windows)}
......
......@@ -129,6 +129,15 @@ changed size when `window-size-change-functions' are run.
* Changes in Emacs 25.2 on Non-Free Operating Systems
** Intercepting hotkeys on Windows 7 and later now works better.
The new keyboard hooking code properly grabs system hotkeys such as
Win-* and Alt-TAB, in a way that Emacs can get at them before the
system. This makes the `w32-register-hot-key' functionality work
again on all versions of MS-Windows starting with Windows 7. On
Windows NT and later you can now register any hotkey combination. (On
Windows 9X, the previous limitations, spelled out in the Emacs manual,
still apply.)
* Installation Changes in Emacs 25.1
......
......@@ -759,6 +759,9 @@ initialize_w32_display (struct terminal *term, int *width, int *height)
/* Setup w32_display_info structure for this frame. */
w32_initialize_display_info (build_string ("Console"));
/* Set up the keyboard hook. */
setup_w32_kbdhook ();
}
......
This diff is collapsed.
......@@ -41,6 +41,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "termchar.h" /* for Mouse_HLInfo, tty_display_info */
#include "w32term.h"
#include "w32inevt.h"
#include "w32common.h"
/* stdin, from w32console.c */
extern HANDLE keyboard_handle;
......@@ -148,10 +149,12 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
switch (event->wVirtualKeyCode)
{
case VK_LWIN:
mod_key_state &= ~LEFT_WIN_PRESSED;
if (!w32_kbdhook_active)
mod_key_state &= ~LEFT_WIN_PRESSED;
break;
case VK_RWIN:
mod_key_state &= ~RIGHT_WIN_PRESSED;
if (!w32_kbdhook_active)
mod_key_state &= ~RIGHT_WIN_PRESSED;
break;
case VK_APPS:
mod_key_state &= ~APPS_PRESSED;
......@@ -185,7 +188,8 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
}
}
mod_key_state |= LEFT_WIN_PRESSED;
if (!w32_kbdhook_active)
mod_key_state |= LEFT_WIN_PRESSED;
if (!NILP (Vw32_lwindow_modifier))
return 0;
break;
......@@ -201,7 +205,8 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
}
}
mod_key_state |= RIGHT_WIN_PRESSED;
if (!w32_kbdhook_active)
mod_key_state |= RIGHT_WIN_PRESSED;
if (!NILP (Vw32_rwindow_modifier))
return 0;
break;
......@@ -267,6 +272,13 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
/* Recognize state of Windows and Apps keys. */
event->dwControlKeyState |= mod_key_state;
if (w32_kbdhook_active)
{
if (check_w32_winkey_state (VK_LWIN))
event->dwControlKeyState |= LEFT_WIN_PRESSED;
if (check_w32_winkey_state (VK_RWIN))
event->dwControlKeyState |= RIGHT_WIN_PRESSED;
}
/* Distinguish numeric keypad keys from extended keys. */
event->wVirtualKeyCode =
......
......@@ -738,6 +738,12 @@ extern int handle_file_notifications (struct input_event *);
extern void w32_initialize_display_info (Lisp_Object);
extern void initialize_w32_display (struct terminal *, int *, int *);
/* Keyboard hooks. */
extern void setup_w32_kbdhook (void);
extern void remove_w32_kbdhook (void);
extern int check_w32_winkey_state (int);
#define w32_kbdhook_active (os_subtype != OS_9X)
/* Keypad command key support. W32 doesn't have virtual keys defined
for the function keys on the keypad (they are mapped to the standard
function keys), so we define our own. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment