diff options
| author | Geoff Voelker | 1998-12-02 23:52:47 +0000 |
|---|---|---|
| committer | Geoff Voelker | 1998-12-02 23:52:47 +0000 |
| commit | adcc38092facc5b5de19c467d71863106cae7b57 (patch) | |
| tree | 8b8e4e6eccbb1cf7f4b3a002e088ce3d33249680 /src | |
| parent | 36f22224e1b22e6a45448ba634cd6ea57e44e152 (diff) | |
| download | emacs-adcc38092facc5b5de19c467d71863106cae7b57.tar.gz emacs-adcc38092facc5b5de19c467d71863106cae7b57.zip | |
(Vw32_phantom_key_code): New variable.
(Qhyper, Qsuper, Qmeta, Qalt, Qctrl, Qcontrol, Qshift): New
variables.
(syms_of_w32fns): Init and register them.
(reset_modifiers): Use a more precise test for whether Emacs has
keyboard focus. Synchronize state of all keys that can be used as
modifiers, to overcome problems arising from hot-keys.
(w32_key_to_modifier): Be careful not to call intern() to avoid
requiring thread synchronization.
(w32_msg_pump): Handle new WM_EMACS_TOGGLE_LOCK_KEY message.
(w32_wnd_proc): Ensure lock key indicator lights are updated
promptly on Windows 9x, by passing key events on to the system.
(w32_wnd_proc): Use Vw32_phantom_key_code to stop system
responding to Windows key events when not wanted.
(w32_wnd_proc): Undo the mapping of Ctrl-Pause into cancel and
Ctrl-NumLock into pause by the system.
(w32_wnd_proc): Don't translate key combinations containing any
modifiers other than shift (and capslock).
(w32_wnd_proc): Reset modifier key states when receiving focus (we
can't determine the key states until we have keyboard focus).
(Fw32_toggle_lock_key): New function.
(syms_of_w32fns): Defsubr it.
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32fns.c | 265 |
1 files changed, 217 insertions, 48 deletions
diff --git a/src/w32fns.c b/src/w32fns.c index b501d19db2d..47423f466f8 100644 --- a/src/w32fns.c +++ b/src/w32fns.c | |||
| @@ -48,6 +48,7 @@ Boston, MA 02111-1307, USA. */ | |||
| 48 | extern void abort (); | 48 | extern void abort (); |
| 49 | extern void free_frame_menubar (); | 49 | extern void free_frame_menubar (); |
| 50 | extern struct scroll_bar *x_window_to_scroll_bar (); | 50 | extern struct scroll_bar *x_window_to_scroll_bar (); |
| 51 | extern int w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state); | ||
| 51 | extern int quit_char; | 52 | extern int quit_char; |
| 52 | 53 | ||
| 53 | extern char *lispy_function_keys[]; | 54 | extern char *lispy_function_keys[]; |
| @@ -70,6 +71,10 @@ Lisp_Object Vw32_pass_lwindow_to_system; | |||
| 70 | only affects whether "tapping" the key opens the Start menu). */ | 71 | only affects whether "tapping" the key opens the Start menu). */ |
| 71 | Lisp_Object Vw32_pass_rwindow_to_system; | 72 | Lisp_Object Vw32_pass_rwindow_to_system; |
| 72 | 73 | ||
| 74 | /* Virtual key code used to generate "phantom" key presses in order | ||
| 75 | to stop system from acting on Windows key events. */ | ||
| 76 | Lisp_Object Vw32_phantom_key_code; | ||
| 77 | |||
| 73 | /* Modifier associated with the left "Windows" key, or nil to act as a | 78 | /* Modifier associated with the left "Windows" key, or nil to act as a |
| 74 | normal key. */ | 79 | normal key. */ |
| 75 | Lisp_Object Vw32_lwindow_modifier; | 80 | Lisp_Object Vw32_lwindow_modifier; |
| @@ -202,6 +207,14 @@ Lisp_Object Quser_position; | |||
| 202 | Lisp_Object Quser_size; | 207 | Lisp_Object Quser_size; |
| 203 | Lisp_Object Qdisplay; | 208 | Lisp_Object Qdisplay; |
| 204 | 209 | ||
| 210 | Lisp_Object Qhyper; | ||
| 211 | Lisp_Object Qsuper; | ||
| 212 | Lisp_Object Qmeta; | ||
| 213 | Lisp_Object Qalt; | ||
| 214 | Lisp_Object Qctrl; | ||
| 215 | Lisp_Object Qcontrol; | ||
| 216 | Lisp_Object Qshift; | ||
| 217 | |||
| 205 | /* State variables for emulating a three button mouse. */ | 218 | /* State variables for emulating a three button mouse. */ |
| 206 | #define LMOUSE 1 | 219 | #define LMOUSE 1 |
| 207 | #define MMOUSE 2 | 220 | #define MMOUSE 2 |
| @@ -3091,16 +3104,13 @@ reset_modifiers () | |||
| 3091 | { | 3104 | { |
| 3092 | SHORT ctrl, alt; | 3105 | SHORT ctrl, alt; |
| 3093 | 3106 | ||
| 3094 | if (!modifiers_recorded) | 3107 | if (GetFocus () == NULL) |
| 3108 | /* Emacs doesn't have keyboard focus. Do nothing. */ | ||
| 3095 | return; | 3109 | return; |
| 3096 | 3110 | ||
| 3097 | ctrl = GetAsyncKeyState (VK_CONTROL); | 3111 | ctrl = GetAsyncKeyState (VK_CONTROL); |
| 3098 | alt = GetAsyncKeyState (VK_MENU); | 3112 | alt = GetAsyncKeyState (VK_MENU); |
| 3099 | 3113 | ||
| 3100 | if (ctrl == 0 || alt == 0) | ||
| 3101 | /* Emacs doesn't have keyboard focus. Do nothing. */ | ||
| 3102 | return; | ||
| 3103 | |||
| 3104 | if (!(ctrl & 0x08000)) | 3114 | if (!(ctrl & 0x08000)) |
| 3105 | /* Clear any recorded control modifier state. */ | 3115 | /* Clear any recorded control modifier state. */ |
| 3106 | modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0; | 3116 | modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0; |
| @@ -3109,8 +3119,27 @@ reset_modifiers () | |||
| 3109 | /* Clear any recorded alt modifier state. */ | 3119 | /* Clear any recorded alt modifier state. */ |
| 3110 | modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0; | 3120 | modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0; |
| 3111 | 3121 | ||
| 3112 | /* Otherwise, leave the modifier state as it was when Emacs lost | 3122 | /* Update the state of all modifier keys, because modifiers used in |
| 3113 | keyboard focus. */ | 3123 | hot-key combinations can get stuck on if Emacs loses focus as a |
| 3124 | result of a hot-key being pressed. */ | ||
| 3125 | { | ||
| 3126 | BYTE keystate[256]; | ||
| 3127 | |||
| 3128 | #define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8) | ||
| 3129 | |||
| 3130 | GetKeyboardState (keystate); | ||
| 3131 | keystate[VK_SHIFT] = CURRENT_STATE (VK_SHIFT); | ||
| 3132 | keystate[VK_CONTROL] = CURRENT_STATE (VK_CONTROL); | ||
| 3133 | keystate[VK_LCONTROL] = CURRENT_STATE (VK_LCONTROL); | ||
| 3134 | keystate[VK_RCONTROL] = CURRENT_STATE (VK_RCONTROL); | ||
| 3135 | keystate[VK_MENU] = CURRENT_STATE (VK_MENU); | ||
| 3136 | keystate[VK_LMENU] = CURRENT_STATE (VK_LMENU); | ||
| 3137 | keystate[VK_RMENU] = CURRENT_STATE (VK_RMENU); | ||
| 3138 | keystate[VK_LWIN] = CURRENT_STATE (VK_LWIN); | ||
| 3139 | keystate[VK_RWIN] = CURRENT_STATE (VK_RWIN); | ||
| 3140 | keystate[VK_APPS] = CURRENT_STATE (VK_APPS); | ||
| 3141 | SetKeyboardState (keystate); | ||
| 3142 | } | ||
| 3114 | } | 3143 | } |
| 3115 | 3144 | ||
| 3116 | /* Synchronize modifier state with what is reported with the current | 3145 | /* Synchronize modifier state with what is reported with the current |
| @@ -3178,19 +3207,25 @@ w32_key_to_modifier (int key) | |||
| 3178 | key_mapping = Qnil; | 3207 | key_mapping = Qnil; |
| 3179 | } | 3208 | } |
| 3180 | 3209 | ||
| 3181 | if (EQ (key_mapping, intern ("hyper"))) | 3210 | /* NB. This code runs in the input thread, asychronously to the lisp |
| 3211 | thread, so we must be careful to ensure access to lisp data is | ||
| 3212 | thread-safe. The following code is safe because the modifier | ||
| 3213 | variable values are updated atomically from lisp and symbols are | ||
| 3214 | not relocated by GC. Also, we don't have to worry about seeing GC | ||
| 3215 | markbits here. */ | ||
| 3216 | if (EQ (key_mapping, Qhyper)) | ||
| 3182 | return hyper_modifier; | 3217 | return hyper_modifier; |
| 3183 | if (EQ (key_mapping, intern ("super"))) | 3218 | if (EQ (key_mapping, Qsuper)) |
| 3184 | return super_modifier; | 3219 | return super_modifier; |
| 3185 | if (EQ (key_mapping, intern ("meta"))) | 3220 | if (EQ (key_mapping, Qmeta)) |
| 3186 | return meta_modifier; | 3221 | return meta_modifier; |
| 3187 | if (EQ (key_mapping, intern ("alt"))) | 3222 | if (EQ (key_mapping, Qalt)) |
| 3188 | return alt_modifier; | 3223 | return alt_modifier; |
| 3189 | if (EQ (key_mapping, intern ("ctrl"))) | 3224 | if (EQ (key_mapping, Qctrl)) |
| 3190 | return ctrl_modifier; | 3225 | return ctrl_modifier; |
| 3191 | if (EQ (key_mapping, intern ("control"))) /* synonym for ctrl */ | 3226 | if (EQ (key_mapping, Qcontrol)) /* synonym for ctrl */ |
| 3192 | return ctrl_modifier; | 3227 | return ctrl_modifier; |
| 3193 | if (EQ (key_mapping, intern ("shift"))) | 3228 | if (EQ (key_mapping, Qshift)) |
| 3194 | return shift_modifier; | 3229 | return shift_modifier; |
| 3195 | 3230 | ||
| 3196 | /* Don't generate any modifier if not explicitly requested. */ | 3231 | /* Don't generate any modifier if not explicitly requested. */ |
| @@ -3404,11 +3439,47 @@ w32_msg_pump (deferred_msg * msg_buf) | |||
| 3404 | focus_window = GetFocus (); | 3439 | focus_window = GetFocus (); |
| 3405 | if (focus_window != NULL) | 3440 | if (focus_window != NULL) |
| 3406 | UnregisterHotKey (focus_window, HOTKEY_ID (msg.wParam)); | 3441 | UnregisterHotKey (focus_window, HOTKEY_ID (msg.wParam)); |
| 3407 | /* Mark item as erased. */ | 3442 | /* Mark item as erased. NB: this code must be |
| 3443 | thread-safe. The next line is okay because the cons | ||
| 3444 | cell is never made into garbage and is not relocated by | ||
| 3445 | GC. */ | ||
| 3408 | XCAR ((Lisp_Object) msg.lParam) = Qnil; | 3446 | XCAR ((Lisp_Object) msg.lParam) = Qnil; |
| 3409 | if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0)) | 3447 | if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0)) |
| 3410 | abort (); | 3448 | abort (); |
| 3411 | break; | 3449 | break; |
| 3450 | case WM_EMACS_TOGGLE_LOCK_KEY: | ||
| 3451 | { | ||
| 3452 | int vk_code = (int) msg.wParam; | ||
| 3453 | int cur_state = (GetKeyState (vk_code) & 1); | ||
| 3454 | Lisp_Object new_state = (Lisp_Object) msg.lParam; | ||
| 3455 | |||
| 3456 | /* NB: This code must be thread-safe. It is safe to | ||
| 3457 | call NILP because symbols are not relocated by GC, | ||
| 3458 | and pointer here is not touched by GC (so the markbit | ||
| 3459 | can't be set). Numbers are safe because they are | ||
| 3460 | immediate values. */ | ||
| 3461 | if (NILP (new_state) | ||
| 3462 | || (NUMBERP (new_state) | ||
| 3463 | && (XUINT (new_state)) & 1 != cur_state)) | ||
| 3464 | { | ||
| 3465 | one_w32_display_info.faked_key = vk_code; | ||
| 3466 | |||
| 3467 | keybd_event ((BYTE) vk_code, | ||
| 3468 | (BYTE) MapVirtualKey (vk_code, 0), | ||
| 3469 | KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); | ||
| 3470 | keybd_event ((BYTE) vk_code, | ||
| 3471 | (BYTE) MapVirtualKey (vk_code, 0), | ||
| 3472 | KEYEVENTF_EXTENDEDKEY | 0, 0); | ||
| 3473 | keybd_event ((BYTE) vk_code, | ||
| 3474 | (BYTE) MapVirtualKey (vk_code, 0), | ||
| 3475 | KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); | ||
| 3476 | cur_state = !cur_state; | ||
| 3477 | } | ||
| 3478 | if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, | ||
| 3479 | cur_state, 0)) | ||
| 3480 | abort (); | ||
| 3481 | } | ||
| 3482 | break; | ||
| 3412 | default: | 3483 | default: |
| 3413 | DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message)); | 3484 | DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message)); |
| 3414 | } | 3485 | } |
| @@ -3638,7 +3709,9 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) | |||
| 3638 | if (dpyinfo->faked_key == wParam) | 3709 | if (dpyinfo->faked_key == wParam) |
| 3639 | { | 3710 | { |
| 3640 | dpyinfo->faked_key = 0; | 3711 | dpyinfo->faked_key = 0; |
| 3641 | return 0; | 3712 | /* Make sure TranslateMessage sees them though. */ |
| 3713 | windows_translate = 1; | ||
| 3714 | goto translate; | ||
| 3642 | } | 3715 | } |
| 3643 | 3716 | ||
| 3644 | /* Synchronize modifiers with current keystroke. */ | 3717 | /* Synchronize modifiers with current keystroke. */ |
| @@ -3658,33 +3731,44 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) | |||
| 3658 | press of Space which we will ignore. */ | 3731 | press of Space which we will ignore. */ |
| 3659 | if (GetAsyncKeyState (wParam) & 1) | 3732 | if (GetAsyncKeyState (wParam) & 1) |
| 3660 | { | 3733 | { |
| 3661 | dpyinfo->faked_key = VK_SPACE; | 3734 | if (NUMBERP (Vw32_phantom_key_code)) |
| 3662 | keybd_event (VK_SPACE, | 3735 | wParam = XUINT (Vw32_phantom_key_code) & 255; |
| 3663 | (BYTE) MapVirtualKey (VK_SPACE, 0), 0, 0); | 3736 | else |
| 3737 | wParam = VK_SPACE; | ||
| 3738 | dpyinfo->faked_key = wParam; | ||
| 3739 | keybd_event (wParam, (BYTE) MapVirtualKey (wParam, 0), 0, 0); | ||
| 3664 | } | 3740 | } |
| 3665 | } | 3741 | } |
| 3666 | if (!NILP (Vw32_lwindow_modifier)) | 3742 | if (!NILP (Vw32_lwindow_modifier)) |
| 3667 | return 0; | 3743 | return 0; |
| 3744 | windows_translate = 1; | ||
| 3668 | break; | 3745 | break; |
| 3669 | case VK_RWIN: | 3746 | case VK_RWIN: |
| 3670 | if (NILP (Vw32_pass_rwindow_to_system)) | 3747 | if (NILP (Vw32_pass_rwindow_to_system)) |
| 3671 | { | 3748 | { |
| 3672 | if (GetAsyncKeyState (wParam) & 1) | 3749 | if (GetAsyncKeyState (wParam) & 1) |
| 3673 | { | 3750 | { |
| 3674 | dpyinfo->faked_key = VK_SPACE; | 3751 | if (NUMBERP (Vw32_phantom_key_code)) |
| 3675 | keybd_event (VK_SPACE, | 3752 | wParam = XUINT (Vw32_phantom_key_code) & 255; |
| 3676 | (BYTE) MapVirtualKey (VK_SPACE, 0), 0, 0); | 3753 | else |
| 3754 | wParam = VK_SPACE; | ||
| 3755 | dpyinfo->faked_key = wParam; | ||
| 3756 | keybd_event (wParam, (BYTE) MapVirtualKey (wParam, 0), 0, 0); | ||
| 3677 | } | 3757 | } |
| 3678 | } | 3758 | } |
| 3679 | if (!NILP (Vw32_rwindow_modifier)) | 3759 | if (!NILP (Vw32_rwindow_modifier)) |
| 3680 | return 0; | 3760 | return 0; |
| 3761 | windows_translate = 1; | ||
| 3681 | break; | 3762 | break; |
| 3682 | case VK_APPS: | 3763 | case VK_APPS: |
| 3683 | if (!NILP (Vw32_apps_modifier)) | 3764 | if (!NILP (Vw32_apps_modifier)) |
| 3684 | return 0; | 3765 | return 0; |
| 3766 | windows_translate = 1; | ||
| 3685 | break; | 3767 | break; |
| 3686 | case VK_MENU: | 3768 | case VK_MENU: |
| 3687 | if (NILP (Vw32_pass_alt_to_system)) | 3769 | if (NILP (Vw32_pass_alt_to_system)) |
| 3770 | /* Prevent DefWindowProc from activating the menu bar if an | ||
| 3771 | Alt key is pressed and released by itself. */ | ||
| 3688 | return 0; | 3772 | return 0; |
| 3689 | windows_translate = 1; | 3773 | windows_translate = 1; |
| 3690 | break; | 3774 | break; |
| @@ -3692,42 +3776,65 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) | |||
| 3692 | /* Decide whether to treat as modifier or function key. */ | 3776 | /* Decide whether to treat as modifier or function key. */ |
| 3693 | if (NILP (Vw32_enable_caps_lock)) | 3777 | if (NILP (Vw32_enable_caps_lock)) |
| 3694 | goto disable_lock_key; | 3778 | goto disable_lock_key; |
| 3695 | return 0; | 3779 | windows_translate = 1; |
| 3780 | break; | ||
| 3696 | case VK_NUMLOCK: | 3781 | case VK_NUMLOCK: |
| 3697 | /* Decide whether to treat as modifier or function key. */ | 3782 | /* Decide whether to treat as modifier or function key. */ |
| 3698 | if (NILP (Vw32_enable_num_lock)) | 3783 | if (NILP (Vw32_enable_num_lock)) |
| 3699 | goto disable_lock_key; | 3784 | goto disable_lock_key; |
| 3700 | return 0; | 3785 | windows_translate = 1; |
| 3786 | break; | ||
| 3701 | case VK_SCROLL: | 3787 | case VK_SCROLL: |
| 3702 | /* Decide whether to treat as modifier or function key. */ | 3788 | /* Decide whether to treat as modifier or function key. */ |
| 3703 | if (NILP (Vw32_scroll_lock_modifier)) | 3789 | if (NILP (Vw32_scroll_lock_modifier)) |
| 3704 | goto disable_lock_key; | 3790 | goto disable_lock_key; |
| 3705 | return 0; | 3791 | windows_translate = 1; |
| 3792 | break; | ||
| 3706 | disable_lock_key: | 3793 | disable_lock_key: |
| 3707 | /* Ensure the appropriate lock key state is off (and the | 3794 | /* Ensure the appropriate lock key state (and indicator light) |
| 3708 | indicator light as well). */ | 3795 | remains in the same state. We do this by faking another |
| 3709 | if (GetAsyncKeyState (wParam) & 0x8000) | 3796 | press of the relevant key. Apparently, this really is the |
| 3710 | { | 3797 | only way to toggle the state of the indicator lights. */ |
| 3711 | /* Fake another press of the relevant key. Apparently, | 3798 | dpyinfo->faked_key = wParam; |
| 3712 | this really is the only way to turn off the indicator. */ | 3799 | keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), |
| 3713 | dpyinfo->faked_key = wParam; | 3800 | KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); |
| 3714 | keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), | 3801 | keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), |
| 3715 | KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); | 3802 | KEYEVENTF_EXTENDEDKEY | 0, 0); |
| 3716 | keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), | 3803 | keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), |
| 3717 | KEYEVENTF_EXTENDEDKEY | 0, 0); | 3804 | KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); |
| 3718 | keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), | 3805 | /* Ensure indicator lights are updated promptly on Windows 9x |
| 3719 | KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); | 3806 | (TranslateMessage apparently does this), after forwarding |
| 3720 | } | 3807 | input event. */ |
| 3808 | post_character_message (hwnd, msg, wParam, lParam, | ||
| 3809 | w32_get_key_modifiers (wParam, lParam)); | ||
| 3810 | windows_translate = 1; | ||
| 3721 | break; | 3811 | break; |
| 3722 | case VK_CONTROL: | 3812 | case VK_CONTROL: |
| 3723 | case VK_SHIFT: | 3813 | case VK_SHIFT: |
| 3724 | case VK_PROCESSKEY: /* Generated by IME. */ | 3814 | case VK_PROCESSKEY: /* Generated by IME. */ |
| 3725 | windows_translate = 1; | 3815 | windows_translate = 1; |
| 3726 | break; | 3816 | break; |
| 3817 | case VK_CANCEL: | ||
| 3818 | /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL, | ||
| 3819 | which is confusing for purposes of key binding; convert | ||
| 3820 | VK_CANCEL events into VK_PAUSE events. */ | ||
| 3821 | wParam = VK_PAUSE; | ||
| 3822 | break; | ||
| 3823 | case VK_PAUSE: | ||
| 3824 | /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing | ||
| 3825 | for purposes of key binding; convert these back into | ||
| 3826 | VK_NUMLOCK events, at least when we want to see NumLock key | ||
| 3827 | presses. (Note that there is never any possibility that | ||
| 3828 | VK_PAUSE with Ctrl really is C-Pause as per above.) */ | ||
| 3829 | if (NILP (Vw32_enable_num_lock) && modifier_set (VK_CONTROL)) | ||
| 3830 | wParam = VK_NUMLOCK; | ||
| 3831 | break; | ||
| 3727 | default: | 3832 | default: |
| 3728 | /* If not defined as a function key, change it to a WM_CHAR message. */ | 3833 | /* If not defined as a function key, change it to a WM_CHAR message. */ |
| 3729 | if (lispy_function_keys[wParam] == 0) | 3834 | if (lispy_function_keys[wParam] == 0) |
| 3730 | { | 3835 | { |
| 3836 | DWORD modifiers = construct_console_modifiers (); | ||
| 3837 | |||
| 3731 | if (!NILP (Vw32_recognize_altgr) | 3838 | if (!NILP (Vw32_recognize_altgr) |
| 3732 | && modifier_set (VK_LCONTROL) && modifier_set (VK_RMENU)) | 3839 | && modifier_set (VK_LCONTROL) && modifier_set (VK_RMENU)) |
| 3733 | { | 3840 | { |
| @@ -3736,11 +3843,11 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) | |||
| 3736 | chords correctly. */ | 3843 | chords correctly. */ |
| 3737 | windows_translate = 1; | 3844 | windows_translate = 1; |
| 3738 | } | 3845 | } |
| 3739 | else if (modifier_set (VK_CONTROL) || modifier_set (VK_MENU)) | 3846 | else if ((modifiers & (~SHIFT_PRESSED & ~CAPSLOCK_ON)) != 0) |
| 3740 | { | 3847 | { |
| 3741 | /* Handle key chords including any modifiers other than shift | 3848 | /* Handle key chords including any modifiers other |
| 3742 | directly, in order to preserve as much modifier information as | 3849 | than shift directly, in order to preserve as much |
| 3743 | possible. */ | 3850 | modifier information as possible. */ |
| 3744 | if ('A' <= wParam && wParam <= 'Z') | 3851 | if ('A' <= wParam && wParam <= 'Z') |
| 3745 | { | 3852 | { |
| 3746 | /* Don't translate modified alphabetic keystrokes, | 3853 | /* Don't translate modified alphabetic keystrokes, |
| @@ -3766,7 +3873,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) | |||
| 3766 | key.wVirtualKeyCode = wParam; | 3873 | key.wVirtualKeyCode = wParam; |
| 3767 | key.wVirtualScanCode = (lParam & 0xFF0000) >> 16; | 3874 | key.wVirtualScanCode = (lParam & 0xFF0000) >> 16; |
| 3768 | key.uChar.AsciiChar = 0; | 3875 | key.uChar.AsciiChar = 0; |
| 3769 | key.dwControlKeyState = construct_console_modifiers (); | 3876 | key.dwControlKeyState = modifiers; |
| 3770 | 3877 | ||
| 3771 | add = w32_kbd_patch_key (&key); | 3878 | add = w32_kbd_patch_key (&key); |
| 3772 | /* 0 means an unrecognised keycode, negative means | 3879 | /* 0 means an unrecognised keycode, negative means |
| @@ -3790,6 +3897,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) | |||
| 3790 | } | 3897 | } |
| 3791 | } | 3898 | } |
| 3792 | 3899 | ||
| 3900 | translate: | ||
| 3793 | if (windows_translate) | 3901 | if (windows_translate) |
| 3794 | { | 3902 | { |
| 3795 | MSG windows_msg = { hwnd, msg, wParam, lParam, 0, {0,0} }; | 3903 | MSG windows_msg = { hwnd, msg, wParam, lParam, 0, {0,0} }; |
| @@ -3860,7 +3968,8 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) | |||
| 3860 | { | 3968 | { |
| 3861 | /* Hold onto message for now. */ | 3969 | /* Hold onto message for now. */ |
| 3862 | mouse_button_timer = | 3970 | mouse_button_timer = |
| 3863 | SetTimer (hwnd, MOUSE_BUTTON_ID, XINT (Vw32_mouse_button_tolerance), NULL); | 3971 | SetTimer (hwnd, MOUSE_BUTTON_ID, |
| 3972 | XINT (Vw32_mouse_button_tolerance), NULL); | ||
| 3864 | saved_mouse_button_msg.msg.hwnd = hwnd; | 3973 | saved_mouse_button_msg.msg.hwnd = hwnd; |
| 3865 | saved_mouse_button_msg.msg.message = msg; | 3974 | saved_mouse_button_msg.msg.message = msg; |
| 3866 | saved_mouse_button_msg.msg.wParam = wParam; | 3975 | saved_mouse_button_msg.msg.wParam = wParam; |
| @@ -3960,7 +4069,8 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) | |||
| 3960 | 4069 | ||
| 3961 | if (saved_mouse_move_msg.msg.hwnd == 0) | 4070 | if (saved_mouse_move_msg.msg.hwnd == 0) |
| 3962 | mouse_move_timer = | 4071 | mouse_move_timer = |
| 3963 | SetTimer (hwnd, MOUSE_MOVE_ID, XINT (Vw32_mouse_move_interval), NULL); | 4072 | SetTimer (hwnd, MOUSE_MOVE_ID, |
| 4073 | XINT (Vw32_mouse_move_interval), NULL); | ||
| 3964 | 4074 | ||
| 3965 | /* Hold onto message for now. */ | 4075 | /* Hold onto message for now. */ |
| 3966 | saved_mouse_move_msg.msg.hwnd = hwnd; | 4076 | saved_mouse_move_msg.msg.hwnd = hwnd; |
| @@ -4146,8 +4256,6 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) | |||
| 4146 | #endif | 4256 | #endif |
| 4147 | 4257 | ||
| 4148 | case WM_ACTIVATEAPP: | 4258 | case WM_ACTIVATEAPP: |
| 4149 | dpyinfo->faked_key = 0; | ||
| 4150 | reset_modifiers (); | ||
| 4151 | case WM_ACTIVATE: | 4259 | case WM_ACTIVATE: |
| 4152 | case WM_WINDOWPOSCHANGED: | 4260 | case WM_WINDOWPOSCHANGED: |
| 4153 | case WM_SHOWWINDOW: | 4261 | case WM_SHOWWINDOW: |
| @@ -4157,6 +4265,8 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) | |||
| 4157 | goto dflt; | 4265 | goto dflt; |
| 4158 | 4266 | ||
| 4159 | case WM_SETFOCUS: | 4267 | case WM_SETFOCUS: |
| 4268 | dpyinfo->faked_key = 0; | ||
| 4269 | reset_modifiers (); | ||
| 4160 | register_hot_keys (hwnd); | 4270 | register_hot_keys (hwnd); |
| 4161 | goto command; | 4271 | goto command; |
| 4162 | case WM_KILLFOCUS: | 4272 | case WM_KILLFOCUS: |
| @@ -6600,6 +6710,39 @@ DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key, Sw32_reconstruct_hot | |||
| 6600 | 6710 | ||
| 6601 | return key; | 6711 | return key; |
| 6602 | } | 6712 | } |
| 6713 | |||
| 6714 | DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key, Sw32_toggle_lock_key, 1, 2, 0, | ||
| 6715 | "Toggle the state of the lock key KEY.\n\ | ||
| 6716 | KEY can be `capslock', `kp-numlock', or `scroll'.\n\ | ||
| 6717 | If the optional parameter NEW-STATE is a number, then the state of KEY\n\ | ||
| 6718 | is set to off if the low bit of NEW-STATE is zero, otherwise on.") | ||
| 6719 | (key, new_state) | ||
| 6720 | Lisp_Object key, new_state; | ||
| 6721 | { | ||
| 6722 | int vk_code; | ||
| 6723 | int cur_state; | ||
| 6724 | |||
| 6725 | if (EQ (key, intern ("capslock"))) | ||
| 6726 | vk_code = VK_CAPITAL; | ||
| 6727 | else if (EQ (key, intern ("kp-numlock"))) | ||
| 6728 | vk_code = VK_NUMLOCK; | ||
| 6729 | else if (EQ (key, intern ("scroll"))) | ||
| 6730 | vk_code = VK_SCROLL; | ||
| 6731 | else | ||
| 6732 | return Qnil; | ||
| 6733 | |||
| 6734 | if (!dwWindowsThreadId) | ||
| 6735 | return make_number (w32_console_toggle_lock_key (vk_code, new_state)); | ||
| 6736 | |||
| 6737 | if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_TOGGLE_LOCK_KEY, | ||
| 6738 | (WPARAM) vk_code, (LPARAM) new_state)) | ||
| 6739 | { | ||
| 6740 | MSG msg; | ||
| 6741 | GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE); | ||
| 6742 | return make_number (msg.wParam); | ||
| 6743 | } | ||
| 6744 | return Qnil; | ||
| 6745 | } | ||
| 6603 | 6746 | ||
| 6604 | syms_of_w32fns () | 6747 | syms_of_w32fns () |
| 6605 | { | 6748 | { |
| @@ -6677,6 +6820,21 @@ syms_of_w32fns () | |||
| 6677 | staticpro (&Qdisplay); | 6820 | staticpro (&Qdisplay); |
| 6678 | /* This is the end of symbol initialization. */ | 6821 | /* This is the end of symbol initialization. */ |
| 6679 | 6822 | ||
| 6823 | Qhyper = intern ("hyper"); | ||
| 6824 | staticpro (&Qhyper); | ||
| 6825 | Qsuper = intern ("super"); | ||
| 6826 | staticpro (&Qsuper); | ||
| 6827 | Qmeta = intern ("meta"); | ||
| 6828 | staticpro (&Qmeta); | ||
| 6829 | Qalt = intern ("alt"); | ||
| 6830 | staticpro (&Qalt); | ||
| 6831 | Qctrl = intern ("ctrl"); | ||
| 6832 | staticpro (&Qctrl); | ||
| 6833 | Qcontrol = intern ("control"); | ||
| 6834 | staticpro (&Qcontrol); | ||
| 6835 | Qshift = intern ("shift"); | ||
| 6836 | staticpro (&Qshift); | ||
| 6837 | |||
| 6680 | Qface_set_after_frame_default = intern ("face-set-after-frame-default"); | 6838 | Qface_set_after_frame_default = intern ("face-set-after-frame-default"); |
| 6681 | staticpro (&Qface_set_after_frame_default); | 6839 | staticpro (&Qface_set_after_frame_default); |
| 6682 | 6840 | ||
| @@ -6715,6 +6873,16 @@ When non-nil, the Start menu is opened by tapping the key."); | |||
| 6715 | When non-nil, the Start menu is opened by tapping the key."); | 6873 | When non-nil, the Start menu is opened by tapping the key."); |
| 6716 | Vw32_pass_rwindow_to_system = Qt; | 6874 | Vw32_pass_rwindow_to_system = Qt; |
| 6717 | 6875 | ||
| 6876 | DEFVAR_INT ("w32-phantom-key-code", | ||
| 6877 | &Vw32_phantom_key_code, | ||
| 6878 | "Virtual key code used to generate \"phantom\" key presses.\n\ | ||
| 6879 | Value is a number between 0 and 255.\n\ | ||
| 6880 | \n\ | ||
| 6881 | Phantom key presses are generated in order to stop the system from\n\ | ||
| 6882 | acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or\n\ | ||
| 6883 | `w32-pass-rwindow-to-system' is nil."); | ||
| 6884 | Vw32_phantom_key_code = VK_SPACE; | ||
| 6885 | |||
| 6718 | DEFVAR_LISP ("w32-enable-num-lock", | 6886 | DEFVAR_LISP ("w32-enable-num-lock", |
| 6719 | &Vw32_enable_num_lock, | 6887 | &Vw32_enable_num_lock, |
| 6720 | "Non-nil if Num Lock should act normally.\n\ | 6888 | "Non-nil if Num Lock should act normally.\n\ |
| @@ -6885,6 +7053,7 @@ displayed according to the current fontset."); | |||
| 6885 | defsubr (&Sw32_unregister_hot_key); | 7053 | defsubr (&Sw32_unregister_hot_key); |
| 6886 | defsubr (&Sw32_registered_hot_keys); | 7054 | defsubr (&Sw32_registered_hot_keys); |
| 6887 | defsubr (&Sw32_reconstruct_hot_key); | 7055 | defsubr (&Sw32_reconstruct_hot_key); |
| 7056 | defsubr (&Sw32_toggle_lock_key); | ||
| 6888 | 7057 | ||
| 6889 | /* Setting callback functions for fontset handler. */ | 7058 | /* Setting callback functions for fontset handler. */ |
| 6890 | get_font_info_func = w32_get_font_info; | 7059 | get_font_info_func = w32_get_font_info; |