diff options
| author | Geoff Voelker | 1998-11-10 20:54:46 +0000 |
|---|---|---|
| committer | Geoff Voelker | 1998-11-10 20:54:46 +0000 |
| commit | ccc2d29c56505a9a7fd38f7e582c16ee38f31b26 (patch) | |
| tree | 77fa1adaf66dbe4a5187d0ad887a3abc88709673 /src | |
| parent | f791da1d45c76c873b09b20e7fe2b70e3d0bfd39 (diff) | |
| download | emacs-ccc2d29c56505a9a7fd38f7e582c16ee38f31b26.tar.gz emacs-ccc2d29c56505a9a7fd38f7e582c16ee38f31b26.zip | |
(Vw32_pass_optional_keys_to_system): Variable removed.
(Vw32_pass_lwindow_to_system):
(Vw32_pass_rwindow_to_system):
(Vw32_lwindow_modifier):
(Vw32_rwindow_modifier):
(Vw32_apps_modifier):
(Vw32_enable_num_lock):
(Vw32_enable_caps_lock):
(Vw32_scroll_lock_modifier): New variables.
(modifier_set): Return toggle state for Scroll Lock.
(w32_key_to_modifier): New function. Returns chosen modifier bit
for given key.
(w32_get_modifiers): Returns modifier flags for
non-keyboard input events.
(construct_console_modifiers): Renamed from construct_modifiers;
recognize Windows and Apps keys as modifiers.
(w32_get_key_modifiers): New function. Returns modifier flags for
keyboard input events.
(map_keypad_keys): Make non-static. Use second arg as extended
flag.
(w32_grabbed_keys): New variable.
(HOTKEY, HOTKEY_ID, HOTKEY_VK_CODE, HOTKEY_MODIFIERS): New macros.
(register_hot_keys):
(unregister_hot_keys):
(lookup_vk_code):
(w32_parse_hot_key):
(Fw32_register_hot_key):
(Fw32_unregister_hot_key):
(Fw32_registered_hot_keys):
(Fw32_reconstruct_hot_key): New functions to support hotkeys.
(post_character_message): New function.
(w32_msg_pump): Handle new messages for using hotkeys and changing
keyboard layout/language.
(w32_wnd_proc): Major rework of keyboard input handling:
optionally recognize Windows keys and Apps key as modifiers;
optionally treat NumLock, CapsLock and ScrollLock as function
keys; let system translate keystrokes to characters to avoid
system bugs relating to dead-key handling; preserve shift
distinction for control characters; forward keyboard
layout/language changes to lisp; detect and convert hot-key events
to normal keystrokes.
(syms_of_w32fns): Register new functions and variables.
(w32_last_error): New function for use in debugging.
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32fns.c | 783 |
1 files changed, 680 insertions, 103 deletions
diff --git a/src/w32fns.c b/src/w32fns.c index 2765c7bbb03..c11c3d5c841 100644 --- a/src/w32fns.c +++ b/src/w32fns.c | |||
| @@ -50,6 +50,8 @@ 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 quit_char; | 51 | extern int quit_char; |
| 52 | 52 | ||
| 53 | extern char *lispy_function_keys[]; | ||
| 54 | |||
| 53 | /* The colormap for converting color names to RGB values */ | 55 | /* The colormap for converting color names to RGB values */ |
| 54 | Lisp_Object Vw32_color_map; | 56 | Lisp_Object Vw32_color_map; |
| 55 | 57 | ||
| @@ -60,9 +62,34 @@ Lisp_Object Vw32_pass_alt_to_system; | |||
| 60 | to alt_modifier. */ | 62 | to alt_modifier. */ |
| 61 | Lisp_Object Vw32_alt_is_meta; | 63 | Lisp_Object Vw32_alt_is_meta; |
| 62 | 64 | ||
| 63 | /* Non nil if left window, right window, and application key events | 65 | /* Non nil if left window key events are passed on to Windows (this only |
| 64 | are passed on to Windows. */ | 66 | affects whether "tapping" the key opens the Start menu). */ |
| 65 | Lisp_Object Vw32_pass_optional_keys_to_system; | 67 | Lisp_Object Vw32_pass_lwindow_to_system; |
| 68 | |||
| 69 | /* 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 | Lisp_Object Vw32_pass_rwindow_to_system; | ||
| 72 | |||
| 73 | /* Modifier associated with the left "Windows" key, or nil to act as a | ||
| 74 | normal key. */ | ||
| 75 | Lisp_Object Vw32_lwindow_modifier; | ||
| 76 | |||
| 77 | /* Modifier associated with the right "Windows" key, or nil to act as a | ||
| 78 | normal key. */ | ||
| 79 | Lisp_Object Vw32_rwindow_modifier; | ||
| 80 | |||
| 81 | /* Modifier associated with the "Apps" key, or nil to act as a normal | ||
| 82 | key. */ | ||
| 83 | Lisp_Object Vw32_apps_modifier; | ||
| 84 | |||
| 85 | /* Value is nil if Num Lock acts as a function key. */ | ||
| 86 | Lisp_Object Vw32_enable_num_lock; | ||
| 87 | |||
| 88 | /* Value is nil if Caps Lock acts as a function key. */ | ||
| 89 | Lisp_Object Vw32_enable_caps_lock; | ||
| 90 | |||
| 91 | /* Modifier associated with Scroll Lock, or nil to act as a normal key. */ | ||
| 92 | Lisp_Object Vw32_scroll_lock_modifier; | ||
| 66 | 93 | ||
| 67 | /* Switch to control whether we inhibit requests for italicised fonts (which | 94 | /* Switch to control whether we inhibit requests for italicised fonts (which |
| 68 | are synthesized, look ugly, and are trashed by cursor movement under NT). */ | 95 | are synthesized, look ugly, and are trashed by cursor movement under NT). */ |
| @@ -205,6 +232,7 @@ extern int last_mouse_scroll_bar_pos; | |||
| 205 | 232 | ||
| 206 | /* From w32term.c. */ | 233 | /* From w32term.c. */ |
| 207 | extern Lisp_Object Vw32_num_mouse_buttons; | 234 | extern Lisp_Object Vw32_num_mouse_buttons; |
| 235 | extern Lisp_Object Vw32_recognize_altgr; | ||
| 208 | 236 | ||
| 209 | 237 | ||
| 210 | /* Error if we are not connected to MS-Windows. */ | 238 | /* Error if we are not connected to MS-Windows. */ |
| @@ -2959,17 +2987,6 @@ w32_createwindow (f) | |||
| 2959 | } | 2987 | } |
| 2960 | } | 2988 | } |
| 2961 | 2989 | ||
| 2962 | /* Convert between the modifier bits W32 uses and the modifier bits | ||
| 2963 | Emacs uses. */ | ||
| 2964 | unsigned int | ||
| 2965 | w32_get_modifiers () | ||
| 2966 | { | ||
| 2967 | return (((GetKeyState (VK_SHIFT)&0x8000) ? shift_modifier : 0) | | ||
| 2968 | ((GetKeyState (VK_CONTROL)&0x8000) ? ctrl_modifier : 0) | | ||
| 2969 | ((GetKeyState (VK_MENU)&0x8000) ? | ||
| 2970 | ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier) : 0)); | ||
| 2971 | } | ||
| 2972 | |||
| 2973 | void | 2990 | void |
| 2974 | my_post_msg (wmsg, hwnd, msg, wParam, lParam) | 2991 | my_post_msg (wmsg, hwnd, msg, wParam, lParam) |
| 2975 | W32Msg * wmsg; | 2992 | W32Msg * wmsg; |
| @@ -3116,7 +3133,7 @@ sync_modifiers () | |||
| 3116 | static int | 3133 | static int |
| 3117 | modifier_set (int vkey) | 3134 | modifier_set (int vkey) |
| 3118 | { | 3135 | { |
| 3119 | if (vkey == VK_CAPITAL) | 3136 | if (vkey == VK_CAPITAL || vkey == VK_SCROLL) |
| 3120 | return (GetKeyState (vkey) & 0x1); | 3137 | return (GetKeyState (vkey) & 0x1); |
| 3121 | if (!modifiers_recorded) | 3138 | if (!modifiers_recorded) |
| 3122 | return (GetKeyState (vkey) & 0x8000); | 3139 | return (GetKeyState (vkey) & 0x8000); |
| @@ -3131,56 +3148,215 @@ modifier_set (int vkey) | |||
| 3131 | return modifiers[EMACS_LMENU]; | 3148 | return modifiers[EMACS_LMENU]; |
| 3132 | case VK_RMENU: | 3149 | case VK_RMENU: |
| 3133 | return modifiers[EMACS_RMENU]; | 3150 | return modifiers[EMACS_RMENU]; |
| 3134 | default: | ||
| 3135 | break; | ||
| 3136 | } | 3151 | } |
| 3137 | return (GetKeyState (vkey) & 0x8000); | 3152 | return (GetKeyState (vkey) & 0x8000); |
| 3138 | } | 3153 | } |
| 3139 | 3154 | ||
| 3155 | /* Convert between the modifier bits W32 uses and the modifier bits | ||
| 3156 | Emacs uses. */ | ||
| 3157 | |||
| 3158 | unsigned int | ||
| 3159 | w32_key_to_modifier (int key) | ||
| 3160 | { | ||
| 3161 | Lisp_Object key_mapping; | ||
| 3162 | |||
| 3163 | switch (key) | ||
| 3164 | { | ||
| 3165 | case VK_LWIN: | ||
| 3166 | key_mapping = Vw32_lwindow_modifier; | ||
| 3167 | break; | ||
| 3168 | case VK_RWIN: | ||
| 3169 | key_mapping = Vw32_rwindow_modifier; | ||
| 3170 | break; | ||
| 3171 | case VK_APPS: | ||
| 3172 | key_mapping = Vw32_apps_modifier; | ||
| 3173 | break; | ||
| 3174 | case VK_SCROLL: | ||
| 3175 | key_mapping = Vw32_scroll_lock_modifier; | ||
| 3176 | break; | ||
| 3177 | default: | ||
| 3178 | key_mapping = Qnil; | ||
| 3179 | } | ||
| 3180 | |||
| 3181 | if (EQ (key_mapping, intern ("hyper"))) | ||
| 3182 | return hyper_modifier; | ||
| 3183 | if (EQ (key_mapping, intern ("super"))) | ||
| 3184 | return super_modifier; | ||
| 3185 | if (EQ (key_mapping, intern ("meta"))) | ||
| 3186 | return meta_modifier; | ||
| 3187 | if (EQ (key_mapping, intern ("alt"))) | ||
| 3188 | return alt_modifier; | ||
| 3189 | if (EQ (key_mapping, intern ("ctrl"))) | ||
| 3190 | return ctrl_modifier; | ||
| 3191 | if (EQ (key_mapping, intern ("control"))) /* synonym for ctrl */ | ||
| 3192 | return ctrl_modifier; | ||
| 3193 | if (EQ (key_mapping, intern ("shift"))) | ||
| 3194 | return shift_modifier; | ||
| 3195 | |||
| 3196 | /* Don't generate any modifier if not explicitly requested. */ | ||
| 3197 | return 0; | ||
| 3198 | } | ||
| 3199 | |||
| 3200 | unsigned int | ||
| 3201 | w32_get_modifiers () | ||
| 3202 | { | ||
| 3203 | return ((modifier_set (VK_SHIFT) ? shift_modifier : 0) | | ||
| 3204 | (modifier_set (VK_CONTROL) ? ctrl_modifier : 0) | | ||
| 3205 | (modifier_set (VK_LWIN) ? w32_key_to_modifier (VK_LWIN) : 0) | | ||
| 3206 | (modifier_set (VK_RWIN) ? w32_key_to_modifier (VK_RWIN) : 0) | | ||
| 3207 | (modifier_set (VK_APPS) ? w32_key_to_modifier (VK_APPS) : 0) | | ||
| 3208 | (modifier_set (VK_SCROLL) ? w32_key_to_modifier (VK_SCROLL) : 0) | | ||
| 3209 | (modifier_set (VK_MENU) ? | ||
| 3210 | ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier) : 0)); | ||
| 3211 | } | ||
| 3212 | |||
| 3140 | /* We map the VK_* modifiers into console modifier constants | 3213 | /* We map the VK_* modifiers into console modifier constants |
| 3141 | so that we can use the same routines to handle both console | 3214 | so that we can use the same routines to handle both console |
| 3142 | and window input. */ | 3215 | and window input. */ |
| 3143 | 3216 | ||
| 3144 | static int | 3217 | static int |
| 3145 | construct_modifiers (unsigned int wparam, unsigned int lparam) | 3218 | construct_console_modifiers () |
| 3146 | { | 3219 | { |
| 3147 | int mods; | 3220 | int mods; |
| 3148 | 3221 | ||
| 3149 | if (wparam != VK_CONTROL && wparam != VK_MENU) | ||
| 3150 | mods = GetLastError (); | ||
| 3151 | |||
| 3152 | mods = 0; | 3222 | mods = 0; |
| 3153 | mods |= (modifier_set (VK_SHIFT)) ? SHIFT_PRESSED : 0; | 3223 | mods |= (modifier_set (VK_SHIFT)) ? SHIFT_PRESSED : 0; |
| 3154 | mods |= (modifier_set (VK_CAPITAL)) ? CAPSLOCK_ON : 0; | 3224 | mods |= (modifier_set (VK_CAPITAL)) ? CAPSLOCK_ON : 0; |
| 3225 | mods |= (modifier_set (VK_SCROLL)) ? SCROLLLOCK_ON : 0; | ||
| 3226 | mods |= (modifier_set (VK_NUMLOCK)) ? NUMLOCK_ON : 0; | ||
| 3155 | mods |= (modifier_set (VK_LCONTROL)) ? LEFT_CTRL_PRESSED : 0; | 3227 | mods |= (modifier_set (VK_LCONTROL)) ? LEFT_CTRL_PRESSED : 0; |
| 3156 | mods |= (modifier_set (VK_RCONTROL)) ? RIGHT_CTRL_PRESSED : 0; | 3228 | mods |= (modifier_set (VK_RCONTROL)) ? RIGHT_CTRL_PRESSED : 0; |
| 3157 | mods |= (modifier_set (VK_LMENU)) ? LEFT_ALT_PRESSED : 0; | 3229 | mods |= (modifier_set (VK_LMENU)) ? LEFT_ALT_PRESSED : 0; |
| 3158 | mods |= (modifier_set (VK_RMENU)) ? RIGHT_ALT_PRESSED : 0; | 3230 | mods |= (modifier_set (VK_RMENU)) ? RIGHT_ALT_PRESSED : 0; |
| 3231 | mods |= (modifier_set (VK_LWIN)) ? LEFT_WIN_PRESSED : 0; | ||
| 3232 | mods |= (modifier_set (VK_RWIN)) ? RIGHT_WIN_PRESSED : 0; | ||
| 3233 | mods |= (modifier_set (VK_APPS)) ? APPS_PRESSED : 0; | ||
| 3159 | 3234 | ||
| 3160 | return mods; | 3235 | return mods; |
| 3161 | } | 3236 | } |
| 3162 | 3237 | ||
| 3163 | static unsigned int | 3238 | static int |
| 3164 | map_keypad_keys (unsigned int wparam, unsigned int lparam) | 3239 | w32_get_key_modifiers (unsigned int wparam, unsigned int lparam) |
| 3165 | { | 3240 | { |
| 3166 | unsigned int extended = (lparam & 0x1000000L); | 3241 | int mods; |
| 3242 | |||
| 3243 | /* Convert to emacs modifiers. */ | ||
| 3244 | mods = w32_kbd_mods_to_emacs (construct_console_modifiers (), wparam); | ||
| 3245 | |||
| 3246 | return mods; | ||
| 3247 | } | ||
| 3167 | 3248 | ||
| 3168 | if (wparam < VK_CLEAR || wparam > VK_DELETE) | 3249 | unsigned int |
| 3169 | return wparam; | 3250 | map_keypad_keys (unsigned int virt_key, unsigned int extended) |
| 3251 | { | ||
| 3252 | if (virt_key < VK_CLEAR || virt_key > VK_DELETE) | ||
| 3253 | return virt_key; | ||
| 3170 | 3254 | ||
| 3171 | if (wparam == VK_RETURN) | 3255 | if (virt_key == VK_RETURN) |
| 3172 | return (extended ? VK_NUMPAD_ENTER : VK_RETURN); | 3256 | return (extended ? VK_NUMPAD_ENTER : VK_RETURN); |
| 3173 | 3257 | ||
| 3174 | if (wparam >= VK_PRIOR && wparam <= VK_DOWN) | 3258 | if (virt_key >= VK_PRIOR && virt_key <= VK_DOWN) |
| 3175 | return (!extended ? (VK_NUMPAD_PRIOR + (wparam - VK_PRIOR)) : wparam); | 3259 | return (!extended ? (VK_NUMPAD_PRIOR + (virt_key - VK_PRIOR)) : virt_key); |
| 3260 | |||
| 3261 | if (virt_key == VK_INSERT || virt_key == VK_DELETE) | ||
| 3262 | return (!extended ? (VK_NUMPAD_INSERT + (virt_key - VK_INSERT)) : virt_key); | ||
| 3263 | |||
| 3264 | if (virt_key == VK_CLEAR) | ||
| 3265 | return (!extended ? VK_NUMPAD_CLEAR : virt_key); | ||
| 3266 | |||
| 3267 | return virt_key; | ||
| 3268 | } | ||
| 3269 | |||
| 3270 | /* List of special key combinations which w32 would normally capture, | ||
| 3271 | but emacs should grab instead. Not directly visible to lisp, to | ||
| 3272 | simplify synchronization. Each item is an integer encoding a virtual | ||
| 3273 | key code and modifier combination to capture. */ | ||
| 3274 | Lisp_Object w32_grabbed_keys; | ||
| 3275 | |||
| 3276 | #define HOTKEY(vk,mods) make_number (((vk) & 255) | ((mods) << 8)) | ||
| 3277 | #define HOTKEY_ID(k) (XFASTINT (k) & 0xbfff) | ||
| 3278 | #define HOTKEY_VK_CODE(k) (XFASTINT (k) & 255) | ||
| 3279 | #define HOTKEY_MODIFIERS(k) (XFASTINT (k) >> 8) | ||
| 3280 | |||
| 3281 | /* Register hot-keys for reserved key combinations when Emacs has | ||
| 3282 | keyboard focus, since this is the only way Emacs can receive key | ||
| 3283 | combinations like Alt-Tab which are used by the system. */ | ||
| 3284 | |||
| 3285 | static void | ||
| 3286 | register_hot_keys (hwnd) | ||
| 3287 | HWND hwnd; | ||
| 3288 | { | ||
| 3289 | Lisp_Object keylist; | ||
| 3290 | |||
| 3291 | /* Use GC_CONSP, since we are called asynchronously. */ | ||
| 3292 | for (keylist = w32_grabbed_keys; GC_CONSP (keylist); keylist = XCDR (keylist)) | ||
| 3293 | { | ||
| 3294 | Lisp_Object key = XCAR (keylist); | ||
| 3295 | |||
| 3296 | /* Deleted entries get set to nil. */ | ||
| 3297 | if (!INTEGERP (key)) | ||
| 3298 | continue; | ||
| 3299 | |||
| 3300 | RegisterHotKey (hwnd, HOTKEY_ID (key), | ||
| 3301 | HOTKEY_MODIFIERS (key), HOTKEY_VK_CODE (key)); | ||
| 3302 | } | ||
| 3303 | } | ||
| 3304 | |||
| 3305 | static void | ||
| 3306 | unregister_hot_keys (hwnd) | ||
| 3307 | HWND hwnd; | ||
| 3308 | { | ||
| 3309 | Lisp_Object keylist; | ||
| 3310 | |||
| 3311 | /* Use GC_CONSP, since we are called asynchronously. */ | ||
| 3312 | for (keylist = w32_grabbed_keys; GC_CONSP (keylist); keylist = XCDR (keylist)) | ||
| 3313 | { | ||
| 3314 | Lisp_Object key = XCAR (keylist); | ||
| 3315 | |||
| 3316 | if (!INTEGERP (key)) | ||
| 3317 | continue; | ||
| 3318 | |||
| 3319 | UnregisterHotKey (hwnd, HOTKEY_ID (key)); | ||
| 3320 | } | ||
| 3321 | } | ||
| 3322 | |||
| 3323 | static void | ||
| 3324 | post_character_message (hwnd, msg, wParam, lParam, modifiers) | ||
| 3325 | HWND hwnd; | ||
| 3326 | UINT msg; | ||
| 3327 | WPARAM wParam; | ||
| 3328 | LPARAM lParam; | ||
| 3329 | DWORD modifiers; | ||
| 3330 | |||
| 3331 | { | ||
| 3332 | W32Msg wmsg; | ||
| 3176 | 3333 | ||
| 3177 | if (wparam == VK_INSERT || wparam == VK_DELETE) | 3334 | wmsg.dwModifiers = modifiers; |
| 3178 | return (!extended ? (VK_NUMPAD_INSERT + (wparam - VK_INSERT)) : wparam); | ||
| 3179 | 3335 | ||
| 3180 | if (wparam == VK_CLEAR) | 3336 | /* Detect quit_char and set quit-flag directly. Note that we |
| 3181 | return (!extended ? VK_NUMPAD_CLEAR : wparam); | 3337 | still need to post a message to ensure the main thread will be |
| 3338 | woken up if blocked in sys_select(), but we do NOT want to post | ||
| 3339 | the quit_char message itself (because it will usually be as if | ||
| 3340 | the user had typed quit_char twice). Instead, we post a dummy | ||
| 3341 | message that has no particular effect. */ | ||
| 3342 | { | ||
| 3343 | int c = wParam; | ||
| 3344 | if (isalpha (c) && wmsg.dwModifiers == ctrl_modifier) | ||
| 3345 | c = make_ctrl_char (c) & 0377; | ||
| 3346 | if (c == quit_char) | ||
| 3347 | { | ||
| 3348 | Vquit_flag = Qt; | ||
| 3349 | |||
| 3350 | /* The choice of message is somewhat arbitrary, as long as | ||
| 3351 | the main thread handler just ignores it. */ | ||
| 3352 | msg = WM_NULL; | ||
| 3353 | |||
| 3354 | /* Interrupt any blocking system calls. */ | ||
| 3355 | signal_quit (); | ||
| 3356 | } | ||
| 3357 | } | ||
| 3182 | 3358 | ||
| 3183 | return wparam; | 3359 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); |
| 3184 | } | 3360 | } |
| 3185 | 3361 | ||
| 3186 | /* Main message dispatch loop. */ | 3362 | /* Main message dispatch loop. */ |
| @@ -3189,6 +3365,8 @@ static void | |||
| 3189 | w32_msg_pump (deferred_msg * msg_buf) | 3365 | w32_msg_pump (deferred_msg * msg_buf) |
| 3190 | { | 3366 | { |
| 3191 | MSG msg; | 3367 | MSG msg; |
| 3368 | int result; | ||
| 3369 | HWND focus_window; | ||
| 3192 | 3370 | ||
| 3193 | msh_mousewheel = RegisterWindowMessage (MSH_MOUSEWHEEL); | 3371 | msh_mousewheel = RegisterWindowMessage (MSH_MOUSEWHEEL); |
| 3194 | 3372 | ||
| @@ -3207,9 +3385,31 @@ w32_msg_pump (deferred_msg * msg_buf) | |||
| 3207 | SetThreadLocale (msg.wParam); | 3385 | SetThreadLocale (msg.wParam); |
| 3208 | /* Reply is not expected. */ | 3386 | /* Reply is not expected. */ |
| 3209 | break; | 3387 | break; |
| 3388 | case WM_EMACS_SETKEYBOARDLAYOUT: | ||
| 3389 | result = (int) ActivateKeyboardLayout ((HKL) msg.wParam, 0); | ||
| 3390 | if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, | ||
| 3391 | result, 0)) | ||
| 3392 | abort (); | ||
| 3393 | break; | ||
| 3394 | case WM_EMACS_REGISTER_HOT_KEY: | ||
| 3395 | focus_window = GetFocus (); | ||
| 3396 | if (focus_window != NULL) | ||
| 3397 | RegisterHotKey (focus_window, | ||
| 3398 | HOTKEY_ID (msg.wParam), | ||
| 3399 | HOTKEY_MODIFIERS (msg.wParam), | ||
| 3400 | HOTKEY_VK_CODE (msg.wParam)); | ||
| 3401 | /* Reply is not expected. */ | ||
| 3402 | break; | ||
| 3403 | case WM_EMACS_UNREGISTER_HOT_KEY: | ||
| 3404 | focus_window = GetFocus (); | ||
| 3405 | if (focus_window != NULL) | ||
| 3406 | UnregisterHotKey (focus_window, HOTKEY_ID (msg.wParam)); | ||
| 3407 | /* Mark item as erased. */ | ||
| 3408 | XCAR ((Lisp_Object) msg.lParam) = Qnil; | ||
| 3409 | if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0)) | ||
| 3410 | abort (); | ||
| 3411 | break; | ||
| 3210 | default: | 3412 | default: |
| 3211 | /* No need to be so draconian! */ | ||
| 3212 | /* abort (); */ | ||
| 3213 | DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message)); | 3413 | DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message)); |
| 3214 | } | 3414 | } |
| 3215 | } | 3415 | } |
| @@ -3326,8 +3526,6 @@ w32_msg_worker (dw) | |||
| 3326 | 3526 | ||
| 3327 | /* Main window procedure */ | 3527 | /* Main window procedure */ |
| 3328 | 3528 | ||
| 3329 | extern char *lispy_function_keys[]; | ||
| 3330 | |||
| 3331 | LRESULT CALLBACK | 3529 | LRESULT CALLBACK |
| 3332 | w32_wnd_proc (hwnd, msg, wParam, lParam) | 3530 | w32_wnd_proc (hwnd, msg, wParam, lParam) |
| 3333 | HWND hwnd; | 3531 | HWND hwnd; |
| @@ -3392,6 +3590,43 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) | |||
| 3392 | return (0); | 3590 | return (0); |
| 3393 | } | 3591 | } |
| 3394 | 3592 | ||
| 3593 | case WM_INPUTLANGCHANGE: | ||
| 3594 | /* Inform lisp thread of keyboard layout changes. */ | ||
| 3595 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | ||
| 3596 | |||
| 3597 | /* Clear dead keys in the keyboard state; for simplicity only | ||
| 3598 | preserve modifier key states. */ | ||
| 3599 | { | ||
| 3600 | int i; | ||
| 3601 | BYTE keystate[256]; | ||
| 3602 | |||
| 3603 | GetKeyboardState (keystate); | ||
| 3604 | for (i = 0; i < 256; i++) | ||
| 3605 | if (1 | ||
| 3606 | && i != VK_SHIFT | ||
| 3607 | && i != VK_LSHIFT | ||
| 3608 | && i != VK_RSHIFT | ||
| 3609 | && i != VK_CAPITAL | ||
| 3610 | && i != VK_NUMLOCK | ||
| 3611 | && i != VK_SCROLL | ||
| 3612 | && i != VK_CONTROL | ||
| 3613 | && i != VK_LCONTROL | ||
| 3614 | && i != VK_RCONTROL | ||
| 3615 | && i != VK_MENU | ||
| 3616 | && i != VK_LMENU | ||
| 3617 | && i != VK_RMENU | ||
| 3618 | && i != VK_LWIN | ||
| 3619 | && i != VK_RWIN) | ||
| 3620 | keystate[i] = 0; | ||
| 3621 | SetKeyboardState (keystate); | ||
| 3622 | } | ||
| 3623 | goto dflt; | ||
| 3624 | |||
| 3625 | case WM_HOTKEY: | ||
| 3626 | /* Synchronize hot keys with normal input. */ | ||
| 3627 | PostMessage (hwnd, WM_KEYDOWN, HIWORD (lParam), 0); | ||
| 3628 | return (0); | ||
| 3629 | |||
| 3395 | case WM_KEYUP: | 3630 | case WM_KEYUP: |
| 3396 | case WM_SYSKEYUP: | 3631 | case WM_SYSKEYUP: |
| 3397 | record_keyup (wParam, lParam); | 3632 | record_keyup (wParam, lParam); |
| @@ -3399,40 +3634,161 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) | |||
| 3399 | 3634 | ||
| 3400 | case WM_KEYDOWN: | 3635 | case WM_KEYDOWN: |
| 3401 | case WM_SYSKEYDOWN: | 3636 | case WM_SYSKEYDOWN: |
| 3637 | /* Ignore keystrokes we fake ourself; see below. */ | ||
| 3638 | if (dpyinfo->faked_key == wParam) | ||
| 3639 | { | ||
| 3640 | dpyinfo->faked_key = 0; | ||
| 3641 | return 0; | ||
| 3642 | } | ||
| 3643 | |||
| 3402 | /* Synchronize modifiers with current keystroke. */ | 3644 | /* Synchronize modifiers with current keystroke. */ |
| 3403 | sync_modifiers (); | 3645 | sync_modifiers (); |
| 3404 | |||
| 3405 | record_keydown (wParam, lParam); | 3646 | record_keydown (wParam, lParam); |
| 3406 | 3647 | wParam = map_keypad_keys (wParam, (lParam & 0x1000000L) != 0); | |
| 3407 | wParam = map_keypad_keys (wParam, lParam); | ||
| 3408 | 3648 | ||
| 3409 | windows_translate = 0; | 3649 | windows_translate = 0; |
| 3410 | switch (wParam) { | 3650 | |
| 3411 | case VK_LWIN: | 3651 | switch (wParam) |
| 3412 | case VK_RWIN: | 3652 | { |
| 3413 | case VK_APPS: | 3653 | case VK_LWIN: |
| 3414 | /* More support for these keys will likely be necessary. */ | 3654 | if (NILP (Vw32_pass_lwindow_to_system)) |
| 3415 | if (!NILP (Vw32_pass_optional_keys_to_system)) | 3655 | { |
| 3656 | /* Prevent system from acting on keyup (which opens the | ||
| 3657 | Start menu if no other key was pressed) by simulating a | ||
| 3658 | press of Space which we will ignore. */ | ||
| 3659 | if (GetAsyncKeyState (wParam) & 1) | ||
| 3660 | { | ||
| 3661 | dpyinfo->faked_key = VK_SPACE; | ||
| 3662 | keybd_event (VK_SPACE, | ||
| 3663 | (BYTE) MapVirtualKey (VK_SPACE, 0), 0, 0); | ||
| 3664 | } | ||
| 3665 | } | ||
| 3666 | if (!NILP (Vw32_lwindow_modifier)) | ||
| 3667 | return 0; | ||
| 3668 | break; | ||
| 3669 | case VK_RWIN: | ||
| 3670 | if (NILP (Vw32_pass_rwindow_to_system)) | ||
| 3671 | { | ||
| 3672 | if (GetAsyncKeyState (wParam) & 1) | ||
| 3673 | { | ||
| 3674 | dpyinfo->faked_key = VK_SPACE; | ||
| 3675 | keybd_event (VK_SPACE, | ||
| 3676 | (BYTE) MapVirtualKey (VK_SPACE, 0), 0, 0); | ||
| 3677 | } | ||
| 3678 | } | ||
| 3679 | if (!NILP (Vw32_rwindow_modifier)) | ||
| 3680 | return 0; | ||
| 3681 | break; | ||
| 3682 | case VK_APPS: | ||
| 3683 | if (!NILP (Vw32_apps_modifier)) | ||
| 3684 | return 0; | ||
| 3685 | break; | ||
| 3686 | case VK_MENU: | ||
| 3687 | if (NILP (Vw32_pass_alt_to_system)) | ||
| 3688 | return 0; | ||
| 3416 | windows_translate = 1; | 3689 | windows_translate = 1; |
| 3417 | break; | 3690 | break; |
| 3418 | case VK_MENU: | 3691 | case VK_CAPITAL: |
| 3419 | if (NILP (Vw32_pass_alt_to_system)) | 3692 | /* Decide whether to treat as modifier or function key. */ |
| 3693 | if (NILP (Vw32_enable_caps_lock)) | ||
| 3694 | goto disable_lock_key; | ||
| 3420 | return 0; | 3695 | return 0; |
| 3421 | windows_translate = 1; | 3696 | case VK_NUMLOCK: |
| 3422 | break; | 3697 | /* Decide whether to treat as modifier or function key. */ |
| 3423 | case VK_CONTROL: | 3698 | if (NILP (Vw32_enable_num_lock)) |
| 3424 | case VK_CAPITAL: | 3699 | goto disable_lock_key; |
| 3425 | case VK_SHIFT: | 3700 | return 0; |
| 3426 | case VK_NUMLOCK: | 3701 | case VK_SCROLL: |
| 3427 | case VK_SCROLL: | 3702 | /* Decide whether to treat as modifier or function key. */ |
| 3428 | windows_translate = 1; | 3703 | if (NILP (Vw32_scroll_lock_modifier)) |
| 3429 | break; | 3704 | goto disable_lock_key; |
| 3430 | default: | 3705 | return 0; |
| 3431 | /* If not defined as a function key, change it to a WM_CHAR message. */ | 3706 | disable_lock_key: |
| 3432 | if (lispy_function_keys[wParam] == 0) | 3707 | /* Ensure the appropriate lock key state is off (and the |
| 3433 | msg = WM_CHAR; | 3708 | indicator light as well). */ |
| 3434 | break; | 3709 | if (GetAsyncKeyState (wParam) & 0x8000) |
| 3435 | } | 3710 | { |
| 3711 | /* Fake another press of the relevant key. Apparently, | ||
| 3712 | this really is the only way to turn off the indicator. */ | ||
| 3713 | dpyinfo->faked_key = wParam; | ||
| 3714 | keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), | ||
| 3715 | KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); | ||
| 3716 | keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), | ||
| 3717 | KEYEVENTF_EXTENDEDKEY | 0, 0); | ||
| 3718 | keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), | ||
| 3719 | KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); | ||
| 3720 | } | ||
| 3721 | break; | ||
| 3722 | case VK_CONTROL: | ||
| 3723 | case VK_SHIFT: | ||
| 3724 | case VK_PROCESSKEY: /* Generated by IME. */ | ||
| 3725 | windows_translate = 1; | ||
| 3726 | break; | ||
| 3727 | default: | ||
| 3728 | /* If not defined as a function key, change it to a WM_CHAR message. */ | ||
| 3729 | if (lispy_function_keys[wParam] == 0) | ||
| 3730 | { | ||
| 3731 | if (!NILP (Vw32_recognize_altgr) | ||
| 3732 | && modifier_set (VK_LCONTROL) && modifier_set (VK_RMENU)) | ||
| 3733 | { | ||
| 3734 | /* Always let TranslateMessage handle AltGr key chords; | ||
| 3735 | for some reason, ToAscii doesn't always process AltGr | ||
| 3736 | chords correctly. */ | ||
| 3737 | windows_translate = 1; | ||
| 3738 | } | ||
| 3739 | else if (modifier_set (VK_CONTROL) || modifier_set (VK_MENU)) | ||
| 3740 | { | ||
| 3741 | /* Handle key chords including any modifiers other than shift | ||
| 3742 | directly, in order to preserve as much modifier information as | ||
| 3743 | possible. */ | ||
| 3744 | if ('A' <= wParam && wParam <= 'Z') | ||
| 3745 | { | ||
| 3746 | /* Don't translate modified alphabetic keystrokes, | ||
| 3747 | so the user doesn't need to constantly switch | ||
| 3748 | layout to type control or meta keystrokes when | ||
| 3749 | the normal layout translates alphabetic | ||
| 3750 | characters to non-ascii characters. */ | ||
| 3751 | if (!modifier_set (VK_SHIFT)) | ||
| 3752 | wParam += ('a' - 'A'); | ||
| 3753 | msg = WM_CHAR; | ||
| 3754 | } | ||
| 3755 | else | ||
| 3756 | { | ||
| 3757 | /* Try to handle other keystrokes by determining the | ||
| 3758 | base character (ie. translating the base key plus | ||
| 3759 | shift modifier). */ | ||
| 3760 | int add; | ||
| 3761 | int isdead = 0; | ||
| 3762 | KEY_EVENT_RECORD key; | ||
| 3763 | |||
| 3764 | key.bKeyDown = TRUE; | ||
| 3765 | key.wRepeatCount = 1; | ||
| 3766 | key.wVirtualKeyCode = wParam; | ||
| 3767 | key.wVirtualScanCode = (lParam & 0xFF0000) >> 16; | ||
| 3768 | key.uChar.AsciiChar = 0; | ||
| 3769 | key.dwControlKeyState = construct_console_modifiers (); | ||
| 3770 | |||
| 3771 | add = w32_kbd_patch_key (&key); | ||
| 3772 | /* 0 means an unrecognised keycode, negative means | ||
| 3773 | dead key. Ignore both. */ | ||
| 3774 | while (--add >= 0) | ||
| 3775 | { | ||
| 3776 | /* Forward asciified character sequence. */ | ||
| 3777 | post_character_message | ||
| 3778 | (hwnd, WM_CHAR, key.uChar.AsciiChar, lParam, | ||
| 3779 | w32_get_key_modifiers (wParam, lParam)); | ||
| 3780 | w32_kbd_patch_key (&key); | ||
| 3781 | } | ||
| 3782 | return 0; | ||
| 3783 | } | ||
| 3784 | } | ||
| 3785 | else | ||
| 3786 | { | ||
| 3787 | /* Let TranslateMessage handle everything else. */ | ||
| 3788 | windows_translate = 1; | ||
| 3789 | } | ||
| 3790 | } | ||
| 3791 | } | ||
| 3436 | 3792 | ||
| 3437 | if (windows_translate) | 3793 | if (windows_translate) |
| 3438 | { | 3794 | { |
| @@ -3447,36 +3803,8 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) | |||
| 3447 | 3803 | ||
| 3448 | case WM_SYSCHAR: | 3804 | case WM_SYSCHAR: |
| 3449 | case WM_CHAR: | 3805 | case WM_CHAR: |
| 3450 | wmsg.dwModifiers = construct_modifiers (wParam, lParam); | 3806 | post_character_message (hwnd, msg, wParam, lParam, |
| 3451 | 3807 | w32_get_key_modifiers (wParam, lParam)); | |
| 3452 | #if 1 | ||
| 3453 | /* Detect quit_char and set quit-flag directly. Note that we | ||
| 3454 | still need to post a message to ensure the main thread will be | ||
| 3455 | woken up if blocked in sys_select(), but we do NOT want to post | ||
| 3456 | the quit_char message itself (because it will usually be as if | ||
| 3457 | the user had typed quit_char twice). Instead, we post a dummy | ||
| 3458 | message that has no particular effect. */ | ||
| 3459 | { | ||
| 3460 | int c = wParam; | ||
| 3461 | if (isalpha (c) && (wmsg.dwModifiers == LEFT_CTRL_PRESSED | ||
| 3462 | || wmsg.dwModifiers == RIGHT_CTRL_PRESSED)) | ||
| 3463 | c = make_ctrl_char (c) & 0377; | ||
| 3464 | if (c == quit_char) | ||
| 3465 | { | ||
| 3466 | Vquit_flag = Qt; | ||
| 3467 | |||
| 3468 | /* The choice of message is somewhat arbitrary, as long as | ||
| 3469 | the main thread handler just ignores it. */ | ||
| 3470 | msg = WM_NULL; | ||
| 3471 | |||
| 3472 | /* Interrupt any blocking system calls. */ | ||
| 3473 | signal_quit (); | ||
| 3474 | } | ||
| 3475 | } | ||
| 3476 | #endif | ||
| 3477 | |||
| 3478 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | ||
| 3479 | |||
| 3480 | break; | 3808 | break; |
| 3481 | 3809 | ||
| 3482 | /* Simulate middle mouse button events when left and right buttons | 3810 | /* Simulate middle mouse button events when left and right buttons |
| @@ -3817,8 +4145,10 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) | |||
| 3817 | goto dflt; | 4145 | goto dflt; |
| 3818 | #endif | 4146 | #endif |
| 3819 | 4147 | ||
| 3820 | case WM_ACTIVATE: | ||
| 3821 | case WM_ACTIVATEAPP: | 4148 | case WM_ACTIVATEAPP: |
| 4149 | dpyinfo->faked_key = 0; | ||
| 4150 | reset_modifiers (); | ||
| 4151 | case WM_ACTIVATE: | ||
| 3822 | case WM_WINDOWPOSCHANGED: | 4152 | case WM_WINDOWPOSCHANGED: |
| 3823 | case WM_SHOWWINDOW: | 4153 | case WM_SHOWWINDOW: |
| 3824 | /* Inform lisp thread that a frame might have just been obscured | 4154 | /* Inform lisp thread that a frame might have just been obscured |
| @@ -3827,11 +4157,14 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) | |||
| 3827 | goto dflt; | 4157 | goto dflt; |
| 3828 | 4158 | ||
| 3829 | case WM_SETFOCUS: | 4159 | case WM_SETFOCUS: |
| 3830 | reset_modifiers (); | 4160 | register_hot_keys (hwnd); |
| 4161 | goto command; | ||
| 3831 | case WM_KILLFOCUS: | 4162 | case WM_KILLFOCUS: |
| 4163 | unregister_hot_keys (hwnd); | ||
| 3832 | case WM_MOVE: | 4164 | case WM_MOVE: |
| 3833 | case WM_SIZE: | 4165 | case WM_SIZE: |
| 3834 | case WM_COMMAND: | 4166 | case WM_COMMAND: |
| 4167 | command: | ||
| 3835 | wmsg.dwModifiers = w32_get_modifiers (); | 4168 | wmsg.dwModifiers = w32_get_modifiers (); |
| 3836 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); | 4169 | my_post_msg (&wmsg, hwnd, msg, wParam, lParam); |
| 3837 | goto dflt; | 4170 | goto dflt; |
| @@ -6086,6 +6419,187 @@ If optional parameter FRAME is not specified, use selected frame.") | |||
| 6086 | return Qnil; | 6419 | return Qnil; |
| 6087 | } | 6420 | } |
| 6088 | 6421 | ||
| 6422 | /* Lookup virtual keycode from string representing the name of a | ||
| 6423 | non-ascii keystroke into the corresponding virtual key, using | ||
| 6424 | lispy_function_keys. */ | ||
| 6425 | static int | ||
| 6426 | lookup_vk_code (char *key) | ||
| 6427 | { | ||
| 6428 | int i; | ||
| 6429 | |||
| 6430 | for (i = 0; i < 256; i++) | ||
| 6431 | if (lispy_function_keys[i] != 0 | ||
| 6432 | && strcmp (lispy_function_keys[i], key) == 0) | ||
| 6433 | return i; | ||
| 6434 | |||
| 6435 | return -1; | ||
| 6436 | } | ||
| 6437 | |||
| 6438 | /* Convert a one-element vector style key sequence to a hot key | ||
| 6439 | definition. */ | ||
| 6440 | static int | ||
| 6441 | w32_parse_hot_key (key) | ||
| 6442 | Lisp_Object key; | ||
| 6443 | { | ||
| 6444 | /* Copied from Fdefine_key and store_in_keymap. */ | ||
| 6445 | register Lisp_Object c; | ||
| 6446 | int vk_code; | ||
| 6447 | int lisp_modifiers; | ||
| 6448 | int w32_modifiers; | ||
| 6449 | struct gcpro gcpro1; | ||
| 6450 | |||
| 6451 | CHECK_VECTOR (key, 0); | ||
| 6452 | |||
| 6453 | if (XFASTINT (Flength (key)) != 1) | ||
| 6454 | return Qnil; | ||
| 6455 | |||
| 6456 | GCPRO1 (key); | ||
| 6457 | |||
| 6458 | c = Faref (key, make_number (0)); | ||
| 6459 | |||
| 6460 | if (CONSP (c) && lucid_event_type_list_p (c)) | ||
| 6461 | c = Fevent_convert_list (c); | ||
| 6462 | |||
| 6463 | UNGCPRO; | ||
| 6464 | |||
| 6465 | if (! INTEGERP (c) && ! SYMBOLP (c)) | ||
| 6466 | error ("Key definition is invalid"); | ||
| 6467 | |||
| 6468 | /* Work out the base key and the modifiers. */ | ||
| 6469 | if (SYMBOLP (c)) | ||
| 6470 | { | ||
| 6471 | c = parse_modifiers (c); | ||
| 6472 | lisp_modifiers = Fcar (Fcdr (c)); | ||
| 6473 | c = Fcar (c); | ||
| 6474 | if (!SYMBOLP (c)) | ||
| 6475 | abort (); | ||
| 6476 | vk_code = lookup_vk_code (XSYMBOL (c)->name->data); | ||
| 6477 | } | ||
| 6478 | else if (INTEGERP (c)) | ||
| 6479 | { | ||
| 6480 | lisp_modifiers = XINT (c) & ~CHARACTERBITS; | ||
| 6481 | /* Many ascii characters are their own virtual key code. */ | ||
| 6482 | vk_code = XINT (c) & CHARACTERBITS; | ||
| 6483 | } | ||
| 6484 | |||
| 6485 | if (vk_code < 0 || vk_code > 255) | ||
| 6486 | return Qnil; | ||
| 6487 | |||
| 6488 | if ((lisp_modifiers & meta_modifier) != 0 | ||
| 6489 | && !NILP (Vw32_alt_is_meta)) | ||
| 6490 | lisp_modifiers |= alt_modifier; | ||
| 6491 | |||
| 6492 | /* Convert lisp modifiers to Windows hot-key form. */ | ||
| 6493 | w32_modifiers = (lisp_modifiers & hyper_modifier) ? MOD_WIN : 0; | ||
| 6494 | w32_modifiers |= (lisp_modifiers & alt_modifier) ? MOD_ALT : 0; | ||
| 6495 | w32_modifiers |= (lisp_modifiers & ctrl_modifier) ? MOD_CONTROL : 0; | ||
| 6496 | w32_modifiers |= (lisp_modifiers & shift_modifier) ? MOD_SHIFT : 0; | ||
| 6497 | |||
| 6498 | return HOTKEY (vk_code, w32_modifiers); | ||
| 6499 | } | ||
| 6500 | |||
| 6501 | DEFUN ("w32-register-hot-key", Fw32_register_hot_key, Sw32_register_hot_key, 1, 1, 0, | ||
| 6502 | "Register KEY as a hot-key combination.\n\ | ||
| 6503 | Certain key combinations like Alt-Tab are reserved for system use on\n\ | ||
| 6504 | Windows, and therefore are normally intercepted by the system. However,\n\ | ||
| 6505 | most of these key combinations can be received by registering them as\n\ | ||
| 6506 | hot-keys, overriding their special meaning.\n\ | ||
| 6507 | \n\ | ||
| 6508 | KEY must be a one element key definition in vector form that would be\n\ | ||
| 6509 | acceptable to `define-key' (e.g. [A-tab] for Alt-Tab). The meta\n\ | ||
| 6510 | modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper\n\ | ||
| 6511 | is always interpreted as the Windows modifier keys.\n\ | ||
| 6512 | \n\ | ||
| 6513 | The return value is the hotkey-id if registered, otherwise nil.") | ||
| 6514 | (key) | ||
| 6515 | Lisp_Object key; | ||
| 6516 | { | ||
| 6517 | key = w32_parse_hot_key (key); | ||
| 6518 | |||
| 6519 | if (NILP (Fmemq (key, w32_grabbed_keys))) | ||
| 6520 | { | ||
| 6521 | /* Reuse an empty slot if possible. */ | ||
| 6522 | Lisp_Object item = Fmemq (Qnil, w32_grabbed_keys); | ||
| 6523 | |||
| 6524 | /* Safe to add new key to list, even if we have focus. */ | ||
| 6525 | if (NILP (item)) | ||
| 6526 | w32_grabbed_keys = Fcons (key, w32_grabbed_keys); | ||
| 6527 | else | ||
| 6528 | XCAR (item) = key; | ||
| 6529 | |||
| 6530 | /* Notify input thread about new hot-key definition, so that it | ||
| 6531 | takes effect without needing to switch focus. */ | ||
| 6532 | PostThreadMessage (dwWindowsThreadId, WM_EMACS_REGISTER_HOT_KEY, | ||
| 6533 | (WPARAM) key, 0); | ||
| 6534 | } | ||
| 6535 | |||
| 6536 | return key; | ||
| 6537 | } | ||
| 6538 | |||
| 6539 | DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key, Sw32_unregister_hot_key, 1, 1, 0, | ||
| 6540 | "Unregister HOTKEY as a hot-key combination.") | ||
| 6541 | (key) | ||
| 6542 | Lisp_Object key; | ||
| 6543 | { | ||
| 6544 | Lisp_Object item; | ||
| 6545 | |||
| 6546 | if (!INTEGERP (key)) | ||
| 6547 | key = w32_parse_hot_key (key); | ||
| 6548 | |||
| 6549 | item = Fmemq (key, w32_grabbed_keys); | ||
| 6550 | |||
| 6551 | if (!NILP (item)) | ||
| 6552 | { | ||
| 6553 | /* Notify input thread about hot-key definition being removed, so | ||
| 6554 | that it takes effect without needing focus switch. */ | ||
| 6555 | if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_UNREGISTER_HOT_KEY, | ||
| 6556 | (WPARAM) XINT (XCAR (item)), (LPARAM) item)) | ||
| 6557 | { | ||
| 6558 | MSG msg; | ||
| 6559 | GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE); | ||
| 6560 | } | ||
| 6561 | return Qt; | ||
| 6562 | } | ||
| 6563 | return Qnil; | ||
| 6564 | } | ||
| 6565 | |||
| 6566 | DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys, Sw32_registered_hot_keys, 0, 0, 0, | ||
| 6567 | "Return list of registered hot-key IDs.") | ||
| 6568 | () | ||
| 6569 | { | ||
| 6570 | return Fcopy_sequence (w32_grabbed_keys); | ||
| 6571 | } | ||
| 6572 | |||
| 6573 | DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key, Sw32_reconstruct_hot_key, 1, 1, 0, | ||
| 6574 | "Convert hot-key ID to a lisp key combination.") | ||
| 6575 | (hotkeyid) | ||
| 6576 | Lisp_Object hotkeyid; | ||
| 6577 | { | ||
| 6578 | int vk_code, w32_modifiers; | ||
| 6579 | Lisp_Object key; | ||
| 6580 | |||
| 6581 | CHECK_NUMBER (hotkeyid, 0); | ||
| 6582 | |||
| 6583 | vk_code = HOTKEY_VK_CODE (hotkeyid); | ||
| 6584 | w32_modifiers = HOTKEY_MODIFIERS (hotkeyid); | ||
| 6585 | |||
| 6586 | if (lispy_function_keys[vk_code]) | ||
| 6587 | key = intern (lispy_function_keys[vk_code]); | ||
| 6588 | else | ||
| 6589 | key = make_number (vk_code); | ||
| 6590 | |||
| 6591 | key = Fcons (key, Qnil); | ||
| 6592 | if (w32_modifiers & MOD_SHIFT) | ||
| 6593 | key = Fcons (intern ("shift"), key); | ||
| 6594 | if (w32_modifiers & MOD_CONTROL) | ||
| 6595 | key = Fcons (intern ("control"), key); | ||
| 6596 | if (w32_modifiers & MOD_ALT) | ||
| 6597 | key = Fcons (intern (NILP (Vw32_alt_is_meta) ? "alt" : "meta"), key); | ||
| 6598 | if (w32_modifiers & MOD_WIN) | ||
| 6599 | key = Fcons (intern ("hyper"), key); | ||
| 6600 | |||
| 6601 | return key; | ||
| 6602 | } | ||
| 6089 | 6603 | ||
| 6090 | syms_of_w32fns () | 6604 | syms_of_w32fns () |
| 6091 | { | 6605 | { |
| @@ -6171,8 +6685,11 @@ syms_of_w32fns () | |||
| 6171 | Fput (Qundefined_color, Qerror_message, | 6685 | Fput (Qundefined_color, Qerror_message, |
| 6172 | build_string ("Undefined color")); | 6686 | build_string ("Undefined color")); |
| 6173 | 6687 | ||
| 6688 | staticpro (&w32_grabbed_keys); | ||
| 6689 | w32_grabbed_keys = Qnil; | ||
| 6690 | |||
| 6174 | DEFVAR_LISP ("w32-color-map", &Vw32_color_map, | 6691 | DEFVAR_LISP ("w32-color-map", &Vw32_color_map, |
| 6175 | "A array of color name mappings for windows."); | 6692 | "An array of color name mappings for windows."); |
| 6176 | Vw32_color_map = Qnil; | 6693 | Vw32_color_map = Qnil; |
| 6177 | 6694 | ||
| 6178 | DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system, | 6695 | DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system, |
| @@ -6186,11 +6703,61 @@ open the System menu. When nil, Emacs silently swallows alt key events."); | |||
| 6186 | When nil, Emacs will translate the alt key to the Alt modifier, and not Meta."); | 6703 | When nil, Emacs will translate the alt key to the Alt modifier, and not Meta."); |
| 6187 | Vw32_alt_is_meta = Qt; | 6704 | Vw32_alt_is_meta = Qt; |
| 6188 | 6705 | ||
| 6189 | DEFVAR_LISP ("w32-pass-optional-keys-to-system", | 6706 | DEFVAR_LISP ("w32-pass-lwindow-to-system", |
| 6190 | &Vw32_pass_optional_keys_to_system, | 6707 | &Vw32_pass_lwindow_to_system, |
| 6191 | "Non-nil if the 'optional' keys (left window, right window,\n\ | 6708 | "Non-nil if the left \"Windows\" key is passed on to Windows.\n\ |
| 6192 | and application keys) are passed on to Windows."); | 6709 | When non-nil, the Start menu is opened by tapping the key."); |
| 6193 | Vw32_pass_optional_keys_to_system = Qnil; | 6710 | Vw32_pass_lwindow_to_system = Qt; |
| 6711 | |||
| 6712 | DEFVAR_LISP ("w32-pass-rwindow-to-system", | ||
| 6713 | &Vw32_pass_rwindow_to_system, | ||
| 6714 | "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."); | ||
| 6716 | Vw32_pass_rwindow_to_system = Qt; | ||
| 6717 | |||
| 6718 | DEFVAR_LISP ("w32-enable-num-lock", | ||
| 6719 | &Vw32_enable_num_lock, | ||
| 6720 | "Non-nil if Num Lock should act normally.\n\ | ||
| 6721 | Set to nil to see Num Lock as the key `kp-numlock'."); | ||
| 6722 | Vw32_enable_num_lock = Qt; | ||
| 6723 | |||
| 6724 | DEFVAR_LISP ("w32-enable-caps-lock", | ||
| 6725 | &Vw32_enable_caps_lock, | ||
| 6726 | "Non-nil if Caps Lock should act normally.\n\ | ||
| 6727 | Set to nil to see Caps Lock as the key `capslock'."); | ||
| 6728 | Vw32_enable_caps_lock = Qt; | ||
| 6729 | |||
| 6730 | DEFVAR_LISP ("w32-scroll-lock-modifier", | ||
| 6731 | &Vw32_scroll_lock_modifier, | ||
| 6732 | "Modifier to use for the Scroll Lock on state.\n\ | ||
| 6733 | The value can be hyper, super, meta, alt, control or shift for the\n\ | ||
| 6734 | respective modifier, or nil to see Scroll Lock as the key `scroll'.\n\ | ||
| 6735 | Any other value will cause the key to be ignored."); | ||
| 6736 | Vw32_scroll_lock_modifier = Qt; | ||
| 6737 | |||
| 6738 | DEFVAR_LISP ("w32-lwindow-modifier", | ||
| 6739 | &Vw32_lwindow_modifier, | ||
| 6740 | "Modifier to use for the left \"Windows\" key.\n\ | ||
| 6741 | The value can be hyper, super, meta, alt, control or shift for the\n\ | ||
| 6742 | respective modifier, or nil to appear as the key `lwindow'.\n\ | ||
| 6743 | Any other value will cause the key to be ignored."); | ||
| 6744 | Vw32_lwindow_modifier = Qnil; | ||
| 6745 | |||
| 6746 | DEFVAR_LISP ("w32-rwindow-modifier", | ||
| 6747 | &Vw32_rwindow_modifier, | ||
| 6748 | "Modifier to use for the right \"Windows\" key.\n\ | ||
| 6749 | The value can be hyper, super, meta, alt, control or shift for the\n\ | ||
| 6750 | respective modifier, or nil to appear as the key `rwindow'.\n\ | ||
| 6751 | Any other value will cause the key to be ignored."); | ||
| 6752 | Vw32_rwindow_modifier = Qnil; | ||
| 6753 | |||
| 6754 | DEFVAR_LISP ("w32-apps-modifier", | ||
| 6755 | &Vw32_apps_modifier, | ||
| 6756 | "Modifier to use for the \"Apps\" key.\n\ | ||
| 6757 | The value can be hyper, super, meta, alt, control or shift for the\n\ | ||
| 6758 | respective modifier, or nil to appear as the key `apps'.\n\ | ||
| 6759 | Any other value will cause the key to be ignored."); | ||
| 6760 | Vw32_apps_modifier = Qnil; | ||
| 6194 | 6761 | ||
| 6195 | DEFVAR_LISP ("w32-enable-italics", &Vw32_enable_italics, | 6762 | DEFVAR_LISP ("w32-enable-italics", &Vw32_enable_italics, |
| 6196 | "Non-nil enables selection of artificially italicized fonts."); | 6763 | "Non-nil enables selection of artificially italicized fonts."); |
| @@ -6314,6 +6881,10 @@ displayed according to the current fontset."); | |||
| 6314 | defsubr (&Sw32_default_color_map); | 6881 | defsubr (&Sw32_default_color_map); |
| 6315 | defsubr (&Sw32_load_color_file); | 6882 | defsubr (&Sw32_load_color_file); |
| 6316 | defsubr (&Sw32_send_sys_command); | 6883 | defsubr (&Sw32_send_sys_command); |
| 6884 | defsubr (&Sw32_register_hot_key); | ||
| 6885 | defsubr (&Sw32_unregister_hot_key); | ||
| 6886 | defsubr (&Sw32_registered_hot_keys); | ||
| 6887 | defsubr (&Sw32_reconstruct_hot_key); | ||
| 6317 | 6888 | ||
| 6318 | /* Setting callback functions for fontset handler. */ | 6889 | /* Setting callback functions for fontset handler. */ |
| 6319 | get_font_info_func = w32_get_font_info; | 6890 | get_font_info_func = w32_get_font_info; |
| @@ -6328,6 +6899,12 @@ displayed according to the current fontset."); | |||
| 6328 | #undef abort | 6899 | #undef abort |
| 6329 | 6900 | ||
| 6330 | void | 6901 | void |
| 6902 | /* For convenience when debugging. */ | ||
| 6903 | int | ||
| 6904 | w32_last_error() | ||
| 6905 | { | ||
| 6906 | return GetLastError (); | ||
| 6907 | } | ||
| 6331 | w32_abort() | 6908 | w32_abort() |
| 6332 | { | 6909 | { |
| 6333 | int button; | 6910 | int button; |