Mercurial > emacs
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; |