aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGeoff Voelker1998-12-02 23:52:47 +0000
committerGeoff Voelker1998-12-02 23:52:47 +0000
commitadcc38092facc5b5de19c467d71863106cae7b57 (patch)
tree8b8e4e6eccbb1cf7f4b3a002e088ce3d33249680 /src
parent36f22224e1b22e6a45448ba634cd6ea57e44e152 (diff)
downloademacs-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.c265
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. */
48extern void abort (); 48extern void abort ();
49extern void free_frame_menubar (); 49extern void free_frame_menubar ();
50extern struct scroll_bar *x_window_to_scroll_bar (); 50extern struct scroll_bar *x_window_to_scroll_bar ();
51extern int w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state);
51extern int quit_char; 52extern int quit_char;
52 53
53extern char *lispy_function_keys[]; 54extern 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). */
71Lisp_Object Vw32_pass_rwindow_to_system; 72Lisp_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. */
76Lisp_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. */
75Lisp_Object Vw32_lwindow_modifier; 80Lisp_Object Vw32_lwindow_modifier;
@@ -202,6 +207,14 @@ Lisp_Object Quser_position;
202Lisp_Object Quser_size; 207Lisp_Object Quser_size;
203Lisp_Object Qdisplay; 208Lisp_Object Qdisplay;
204 209
210Lisp_Object Qhyper;
211Lisp_Object Qsuper;
212Lisp_Object Qmeta;
213Lisp_Object Qalt;
214Lisp_Object Qctrl;
215Lisp_Object Qcontrol;
216Lisp_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
6714DEFUN ("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\
6716KEY can be `capslock', `kp-numlock', or `scroll'.\n\
6717If the optional parameter NEW-STATE is a number, then the state of KEY\n\
6718is 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
6604syms_of_w32fns () 6747syms_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.");
6715When non-nil, the Start menu is opened by tapping the key."); 6873When 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\
6879Value is a number between 0 and 255.\n\
6880\n\
6881Phantom key presses are generated in order to stop the system from\n\
6882acting 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;