comparison src/w32fns.c @ 23803:f112aa8f8f5d

(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.
author Geoff Voelker <voelker@cs.washington.edu>
date Wed, 02 Dec 1998 23:52:47 +0000
parents 119fd94ae526
children d8f8533db4cc
comparison
equal deleted inserted replaced
23802:4052a2875390 23803:f112aa8f8f5d
46 #include <shellapi.h> 46 #include <shellapi.h>
47 47
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[];
54 55
55 /* The colormap for converting color names to RGB values */ 56 /* The colormap for converting color names to RGB values */
67 Lisp_Object Vw32_pass_lwindow_to_system; 68 Lisp_Object Vw32_pass_lwindow_to_system;
68 69
69 /* Non nil if right window key events are passed on to Windows (this 70 /* Non nil if right window key events are passed on to Windows (this
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;
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;
72 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;
76 81
199 Lisp_Object Qx_frame_parameter; 204 Lisp_Object Qx_frame_parameter;
200 Lisp_Object Qx_resource_name; 205 Lisp_Object Qx_resource_name;
201 Lisp_Object Quser_position; 206 Lisp_Object Quser_position;
202 Lisp_Object Quser_size; 207 Lisp_Object Quser_size;
203 Lisp_Object Qdisplay; 208 Lisp_Object Qdisplay;
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;
204 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
208 #define RMOUSE 4 221 #define RMOUSE 4
3089 static void 3102 static void
3090 reset_modifiers () 3103 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
3100 if (ctrl == 0 || alt == 0)
3101 /* Emacs doesn't have keyboard focus. Do nothing. */
3102 return;
3103 3113
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;
3107 3117
3108 if (!(alt & 0x08000)) 3118 if (!(alt & 0x08000))
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
3117 keystroke. Even if we cannot distinguish between left and right 3146 keystroke. Even if we cannot distinguish between left and right
3118 modifier keys, we know that, if no modifiers are set, then neither 3147 modifier keys, we know that, if no modifiers are set, then neither
3176 break; 3205 break;
3177 default: 3206 default:
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. */
3197 return 0; 3232 return 0;
3198 } 3233 }
3402 break; 3437 break;
3403 case WM_EMACS_UNREGISTER_HOT_KEY: 3438 case WM_EMACS_UNREGISTER_HOT_KEY:
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 ();
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 }
3411 break; 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 }
3415 } 3486 }
3636 case WM_SYSKEYDOWN: 3707 case WM_SYSKEYDOWN:
3637 /* Ignore keystrokes we fake ourself; see below. */ 3708 /* Ignore keystrokes we fake ourself; see below. */
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. */
3645 sync_modifiers (); 3718 sync_modifiers ();
3646 record_keydown (wParam, lParam); 3719 record_keydown (wParam, lParam);
3656 /* Prevent system from acting on keyup (which opens the 3729 /* Prevent system from acting on keyup (which opens the
3657 Start menu if no other key was pressed) by simulating a 3730 Start menu if no other key was pressed) by simulating a
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;
3691 case VK_CAPITAL: 3775 case VK_CAPITAL:
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 {
3734 /* Always let TranslateMessage handle AltGr key chords; 3841 /* Always let TranslateMessage handle AltGr key chords;
3735 for some reason, ToAscii doesn't always process AltGr 3842 for some reason, ToAscii doesn't always process AltGr
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,
3747 so the user doesn't need to constantly switch 3854 so the user doesn't need to constantly switch
3748 layout to type control or meta keystrokes when 3855 layout to type control or meta keystrokes when
3764 key.bKeyDown = TRUE; 3871 key.bKeyDown = TRUE;
3765 key.wRepeatCount = 1; 3872 key.wRepeatCount = 1;
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
3773 dead key. Ignore both. */ 3880 dead key. Ignore both. */
3774 while (--add >= 0) 3881 while (--add >= 0)
3788 windows_translate = 1; 3895 windows_translate = 1;
3789 } 3896 }
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} };
3796 3904
3797 windows_msg.time = GetMessageTime (); 3905 windows_msg.time = GetMessageTime ();
3858 } 3966 }
3859 else 3967 else
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;
3867 saved_mouse_button_msg.msg.lParam = lParam; 3976 saved_mouse_button_msg.msg.lParam = lParam;
3868 saved_mouse_button_msg.msg.time = GetMessageTime (); 3977 saved_mouse_button_msg.msg.time = GetMessageTime ();
3958 If we get more events before the timer from the first message 4067 If we get more events before the timer from the first message
3959 expires, we just replace the first message. */ 4068 expires, we just replace the first message. */
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;
3967 saved_mouse_move_msg.msg.message = msg; 4077 saved_mouse_move_msg.msg.message = msg;
3968 saved_mouse_move_msg.msg.wParam = wParam; 4078 saved_mouse_move_msg.msg.wParam = wParam;
4144 return MA_ACTIVATEANDEAT; 4254 return MA_ACTIVATEANDEAT;
4145 goto dflt; 4255 goto dflt;
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:
4154 /* Inform lisp thread that a frame might have just been obscured 4262 /* Inform lisp thread that a frame might have just been obscured
4155 or exposed, so should recheck visibility of all frames. */ 4263 or exposed, so should recheck visibility of all frames. */
4156 my_post_msg (&wmsg, hwnd, msg, wParam, lParam); 4264 my_post_msg (&wmsg, 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:
4163 unregister_hot_keys (hwnd); 4273 unregister_hot_keys (hwnd);
4164 case WM_MOVE: 4274 case WM_MOVE:
6597 key = Fcons (intern (NILP (Vw32_alt_is_meta) ? "alt" : "meta"), key); 6707 key = Fcons (intern (NILP (Vw32_alt_is_meta) ? "alt" : "meta"), key);
6598 if (w32_modifiers & MOD_WIN) 6708 if (w32_modifiers & MOD_WIN)
6599 key = Fcons (intern ("hyper"), key); 6709 key = Fcons (intern ("hyper"), key);
6600 6710
6601 return key; 6711 return key;
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;
6602 } 6745 }
6603 6746
6604 syms_of_w32fns () 6747 syms_of_w32fns ()
6605 { 6748 {
6606 /* This is zero if not using MS-Windows. */ 6749 /* This is zero if not using MS-Windows. */
6675 staticpro (&Quser_size); 6818 staticpro (&Quser_size);
6676 Qdisplay = intern ("display"); 6819 Qdisplay = intern ("display");
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
6683 Fput (Qundefined_color, Qerror_conditions, 6841 Fput (Qundefined_color, Qerror_conditions,
6684 Fcons (Qundefined_color, Fcons (Qerror, Qnil))); 6842 Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
6712 DEFVAR_LISP ("w32-pass-rwindow-to-system", 6870 DEFVAR_LISP ("w32-pass-rwindow-to-system",
6713 &Vw32_pass_rwindow_to_system, 6871 &Vw32_pass_rwindow_to_system,
6714 "Non-nil if the right \"Windows\" key is passed on to Windows.\n\ 6872 "Non-nil if the right \"Windows\" key is passed on to Windows.\n\
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;
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;
6717 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\
6721 Set to nil to see Num Lock as the key `kp-numlock'."); 6889 Set to nil to see Num Lock as the key `kp-numlock'.");
6883 defsubr (&Sw32_send_sys_command); 7051 defsubr (&Sw32_send_sys_command);
6884 defsubr (&Sw32_register_hot_key); 7052 defsubr (&Sw32_register_hot_key);
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;
6891 list_fonts_func = w32_list_fonts; 7060 list_fonts_func = w32_list_fonts;
6892 load_font_func = w32_load_font; 7061 load_font_func = w32_load_font;