1 /* Input event support for Emacs on the Microsoft W32 API.
2 Copyright (C) 1992-1993, 1995, 2001-2011 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 Adapted from ntkbd.c by Tim Fleehart
37 #include "dispextern.h"
38 #include "blockinput.h"
39 #include "termhooks.h"
43 /* stdin, from ntterm */
44 extern HANDLE keyboard_handle
;
46 /* Info for last mouse motion */
47 static COORD movement_pos
;
48 static DWORD movement_time
;
51 extern void reinvoke_input_signal (void);
53 extern unsigned int map_keypad_keys (unsigned int, unsigned int);
55 extern unsigned int w32_key_to_modifier (int key
);
58 #define EVENT_QUEUE_SIZE 50
59 static INPUT_RECORD event_queue
[EVENT_QUEUE_SIZE
];
60 static INPUT_RECORD
*queue_ptr
= event_queue
, *queue_end
= event_queue
;
62 /* Temporarily store lead byte of DBCS input sequences. */
63 static char dbcs_lead
= 0;
66 fill_queue (BOOL block
)
71 if (queue_ptr
< queue_end
)
72 return queue_end
-queue_ptr
;
76 /* Check to see if there are some events to read before we try
77 because we can't block. */
78 if (!GetNumberOfConsoleInputEvents (keyboard_handle
, &events_waiting
))
80 if (events_waiting
== 0)
84 rc
= ReadConsoleInput (keyboard_handle
, event_queue
, EVENT_QUEUE_SIZE
,
88 queue_ptr
= event_queue
;
89 queue_end
= event_queue
+ events_waiting
;
90 return (int) events_waiting
;
93 /* In a generic, multi-frame world this should take a console handle
94 and return the frame for it
96 Right now, there's only one frame so return it. */
100 return SELECTED_FRAME ();
103 /* Translate console modifiers to emacs modifiers.
104 German keyboard support (Kai Morgan Zeise 2/18/95). */
106 w32_kbd_mods_to_emacs (DWORD mods
, WORD key
)
110 /* If we recognize right-alt and left-ctrl as AltGr, and it has been
111 pressed, first remove those modifiers. */
112 if (!NILP (Vw32_recognize_altgr
)
113 && (mods
& (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
))
114 == (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
))
115 mods
&= ~ (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
);
117 if (mods
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
118 retval
= ((NILP (Vw32_alt_is_meta
)) ? alt_modifier
: meta_modifier
);
120 if (mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
122 retval
|= ctrl_modifier
;
123 if ((mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
124 == (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
125 retval
|= meta_modifier
;
128 if (mods
& LEFT_WIN_PRESSED
)
129 retval
|= w32_key_to_modifier (VK_LWIN
);
130 if (mods
& RIGHT_WIN_PRESSED
)
131 retval
|= w32_key_to_modifier (VK_RWIN
);
132 if (mods
& APPS_PRESSED
)
133 retval
|= w32_key_to_modifier (VK_APPS
);
134 if (mods
& SCROLLLOCK_ON
)
135 retval
|= w32_key_to_modifier (VK_SCROLL
);
137 /* Just in case someone wanted the original behavior, make it
138 optional by setting w32-capslock-is-shiftlock to t. */
139 if (NILP (Vw32_capslock_is_shiftlock
)
140 /* Keys that should _not_ be affected by CapsLock. */
141 && ( (key
== VK_BACK
)
144 || (key
== VK_RETURN
)
145 || (key
== VK_ESCAPE
)
146 || ((key
>= VK_SPACE
) && (key
<= VK_HELP
))
147 || ((key
>= VK_NUMPAD0
) && (key
<= VK_F24
))
148 || ((key
>= VK_NUMPAD_CLEAR
) && (key
<= VK_NUMPAD_DELETE
))
151 /* Only consider shift state. */
152 if ((mods
& SHIFT_PRESSED
) != 0)
153 retval
|= shift_modifier
;
157 /* Ignore CapsLock state if not enabled. */
158 if (NILP (Vw32_enable_caps_lock
))
159 mods
&= ~CAPSLOCK_ON
;
160 if ((mods
& (SHIFT_PRESSED
| CAPSLOCK_ON
)) != 0)
161 retval
|= shift_modifier
;
168 /* Return nonzero if the virtual key is a dead key. */
170 is_dead_key (int wparam
)
172 unsigned int code
= MapVirtualKey (wparam
, 2);
174 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
175 return (code
& 0x80008000) ? 1 : 0;
179 /* The return code indicates key code size. */
181 w32_kbd_patch_key (KEY_EVENT_RECORD
*event
)
183 unsigned int key_code
= event
->wVirtualKeyCode
;
184 unsigned int mods
= event
->dwControlKeyState
;
186 static BYTE ansi_code
[4];
187 static int isdead
= 0;
191 event
->uChar
.AsciiChar
= ansi_code
[2];
195 if (event
->uChar
.AsciiChar
!= 0)
198 memset (keystate
, 0, sizeof (keystate
));
199 keystate
[key_code
] = 0x80;
200 if (mods
& SHIFT_PRESSED
)
201 keystate
[VK_SHIFT
] = 0x80;
202 if (mods
& CAPSLOCK_ON
)
203 keystate
[VK_CAPITAL
] = 1;
204 /* If we recognize right-alt and left-ctrl as AltGr, set the key
205 states accordingly before invoking ToAscii. */
206 if (!NILP (Vw32_recognize_altgr
)
207 && (mods
& LEFT_CTRL_PRESSED
) && (mods
& RIGHT_ALT_PRESSED
))
209 keystate
[VK_CONTROL
] = 0x80;
210 keystate
[VK_LCONTROL
] = 0x80;
211 keystate
[VK_MENU
] = 0x80;
212 keystate
[VK_RMENU
] = 0x80;
216 /* Because of an OS bug, ToAscii corrupts the stack when called to
217 convert a dead key in console mode on NT4. Unfortunately, trying
218 to check for dead keys using MapVirtualKey doesn't work either -
219 these functions apparently use internal information about keyboard
220 layout which doesn't get properly updated in console programs when
221 changing layout (though apparently it gets partly updated,
222 otherwise ToAscii wouldn't crash). */
223 if (is_dead_key (event
->wVirtualKeyCode
))
227 /* On NT, call ToUnicode instead and then convert to the current
228 locale's default codepage. */
229 if (os_subtype
== OS_NT
)
233 isdead
= ToUnicode (event
->wVirtualKeyCode
, event
->wVirtualScanCode
,
234 keystate
, buf
, 128, 0);
240 event
->uChar
.UnicodeChar
= buf
[isdead
- 1];
242 GetLocaleInfo (GetThreadLocale (),
243 LOCALE_IDEFAULTANSICODEPAGE
, cp
, 20);
245 isdead
= WideCharToMultiByte (cpId
, 0, buf
, isdead
,
246 ansi_code
, 4, NULL
, NULL
);
253 isdead
= ToAscii (event
->wVirtualKeyCode
, event
->wVirtualScanCode
,
254 keystate
, (LPWORD
) ansi_code
, 0);
259 event
->uChar
.AsciiChar
= ansi_code
[0];
264 extern const char *const lispy_function_keys
[];
266 static int faked_key
= 0;
268 /* return code -1 means that event_queue_ptr won't be incremented.
269 In other word, this event makes two key codes. (by himi) */
271 key_event (KEY_EVENT_RECORD
*event
, struct input_event
*emacs_ev
, int *isdead
)
273 static int mod_key_state
= 0;
278 /* Skip key-up events. */
279 if (!event
->bKeyDown
)
281 switch (event
->wVirtualKeyCode
)
284 mod_key_state
&= ~LEFT_WIN_PRESSED
;
287 mod_key_state
&= ~RIGHT_WIN_PRESSED
;
290 mod_key_state
&= ~APPS_PRESSED
;
296 /* Ignore keystrokes we fake ourself; see below. */
297 if (faked_key
== event
->wVirtualKeyCode
)
303 /* To make it easier to debug this code, ignore modifier keys! */
304 switch (event
->wVirtualKeyCode
)
307 if (NILP (Vw32_pass_lwindow_to_system
))
309 /* Prevent system from acting on keyup (which opens the Start
310 menu if no other key was pressed) by simulating a press of
311 Space which we will ignore. */
312 if ((mod_key_state
& LEFT_WIN_PRESSED
) == 0)
314 if (NUMBERP (Vw32_phantom_key_code
))
315 faked_key
= XUINT (Vw32_phantom_key_code
) & 255;
317 faked_key
= VK_SPACE
;
318 keybd_event (faked_key
, (BYTE
) MapVirtualKey (faked_key
, 0), 0, 0);
321 mod_key_state
|= LEFT_WIN_PRESSED
;
322 if (!NILP (Vw32_lwindow_modifier
))
326 if (NILP (Vw32_pass_rwindow_to_system
))
328 if ((mod_key_state
& RIGHT_WIN_PRESSED
) == 0)
330 if (NUMBERP (Vw32_phantom_key_code
))
331 faked_key
= XUINT (Vw32_phantom_key_code
) & 255;
333 faked_key
= VK_SPACE
;
334 keybd_event (faked_key
, (BYTE
) MapVirtualKey (faked_key
, 0), 0, 0);
337 mod_key_state
|= RIGHT_WIN_PRESSED
;
338 if (!NILP (Vw32_rwindow_modifier
))
342 mod_key_state
|= APPS_PRESSED
;
343 if (!NILP (Vw32_apps_modifier
))
347 /* Decide whether to treat as modifier or function key. */
348 if (NILP (Vw32_enable_caps_lock
))
349 goto disable_lock_key
;
352 /* Decide whether to treat as modifier or function key. */
353 if (NILP (Vw32_enable_num_lock
))
354 goto disable_lock_key
;
357 /* Decide whether to treat as modifier or function key. */
358 if (NILP (Vw32_scroll_lock_modifier
))
359 goto disable_lock_key
;
362 /* Ensure the appropriate lock key state is off (and the
363 indicator light as well). */
364 wParam
= event
->wVirtualKeyCode
;
365 if (GetAsyncKeyState (wParam
) & 0x8000)
367 /* Fake another press of the relevant key. Apparently, this
368 really is the only way to turn off the indicator. */
370 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
371 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
372 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
373 KEYEVENTF_EXTENDEDKEY
| 0, 0);
374 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
375 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
383 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
384 which is confusing for purposes of key binding; convert
385 VK_CANCEL events into VK_PAUSE events. */
386 event
->wVirtualKeyCode
= VK_PAUSE
;
389 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
390 for purposes of key binding; convert these back into
391 VK_NUMLOCK events, at least when we want to see NumLock key
392 presses. (Note that there is never any possibility that
393 VK_PAUSE with Ctrl really is C-Pause as per above.) */
394 if (NILP (Vw32_enable_num_lock
)
395 && (event
->dwControlKeyState
396 & (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)) != 0)
397 event
->wVirtualKeyCode
= VK_NUMLOCK
;
401 /* Recognize state of Windows and Apps keys. */
402 event
->dwControlKeyState
|= mod_key_state
;
404 /* Distinguish numeric keypad keys from extended keys. */
405 event
->wVirtualKeyCode
=
406 map_keypad_keys (event
->wVirtualKeyCode
,
407 (event
->dwControlKeyState
& ENHANCED_KEY
));
409 if (lispy_function_keys
[event
->wVirtualKeyCode
] == 0)
411 if (!NILP (Vw32_recognize_altgr
)
412 && (event
->dwControlKeyState
& LEFT_CTRL_PRESSED
)
413 && (event
->dwControlKeyState
& RIGHT_ALT_PRESSED
))
415 /* Don't try to interpret AltGr key chords; ToAscii seems not
416 to process them correctly. */
418 /* Handle key chords including any modifiers other than shift
419 directly, in order to preserve as much modifier information as
421 else if (event
->dwControlKeyState
422 & ( RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
423 | RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
424 | (!NILP (Vw32_lwindow_modifier
) ? LEFT_WIN_PRESSED
: 0)
425 | (!NILP (Vw32_rwindow_modifier
) ? RIGHT_WIN_PRESSED
: 0)
426 | (!NILP (Vw32_apps_modifier
) ? APPS_PRESSED
: 0)
427 | (!NILP (Vw32_scroll_lock_modifier
) ? SCROLLLOCK_ON
: 0)))
429 /* Don't translate modified alphabetic keystrokes, so the user
430 doesn't need to constantly switch layout to type control or
431 meta keystrokes when the normal layout translates
432 alphabetic characters to non-ascii characters. */
433 if ('A' <= event
->wVirtualKeyCode
&& event
->wVirtualKeyCode
<= 'Z')
435 event
->uChar
.AsciiChar
= event
->wVirtualKeyCode
;
436 if ((event
->dwControlKeyState
& SHIFT_PRESSED
) == 0)
437 event
->uChar
.AsciiChar
+= ('a' - 'A');
439 /* Try to handle unrecognized keystrokes by determining the
440 base character (ie. translating the base key plus shift
442 else if (event
->uChar
.AsciiChar
== 0)
443 w32_kbd_patch_key (event
);
446 if (event
->uChar
.AsciiChar
== 0)
448 emacs_ev
->kind
= NO_EVENT
;
451 else if (event
->uChar
.AsciiChar
> 0)
453 emacs_ev
->kind
= ASCII_KEYSTROKE_EVENT
;
454 emacs_ev
->code
= event
->uChar
.AsciiChar
;
456 else if (event
->uChar
.UnicodeChar
> 0)
458 emacs_ev
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
459 emacs_ev
->code
= event
->uChar
.UnicodeChar
;
463 /* Fallback for non-Unicode versions of Windows. */
469 /* Get the codepage to interpret this key with. */
470 GetLocaleInfo (GetThreadLocale (),
471 LOCALE_IDEFAULTANSICODEPAGE
, cp
, 20);
475 dbcs
[1] = event
->uChar
.AsciiChar
;
479 if (!MultiByteToWideChar (cpId
, 0, dbcs
, 2, &code
, 1))
482 DebPrint (("Invalid DBCS sequence: %d %d\n",
484 emacs_ev
->kind
= NO_EVENT
;
487 else if (IsDBCSLeadByteEx (cpId
, dbcs
[1]))
490 emacs_ev
->kind
= NO_EVENT
;
494 if (!MultiByteToWideChar (cpId
, 0, &dbcs
[1], 1, &code
, 1))
497 DebPrint (("Invalid character: %d\n", dbcs
[1]));
498 emacs_ev
->kind
= NO_EVENT
;
501 emacs_ev
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
502 emacs_ev
->code
= code
;
507 emacs_ev
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
508 emacs_ev
->code
= event
->wVirtualKeyCode
;
511 XSETFRAME (emacs_ev
->frame_or_window
, get_frame ());
512 emacs_ev
->modifiers
= w32_kbd_mods_to_emacs (event
->dwControlKeyState
,
513 event
->wVirtualKeyCode
);
514 emacs_ev
->timestamp
= GetTickCount ();
519 w32_console_toggle_lock_key (int vk_code
, Lisp_Object new_state
)
521 int cur_state
= (GetKeyState (vk_code
) & 1);
524 || (NUMBERP (new_state
)
525 && ((XUINT (new_state
)) & 1) != cur_state
))
529 keybd_event ((BYTE
) vk_code
,
530 (BYTE
) MapVirtualKey (vk_code
, 0),
531 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
532 keybd_event ((BYTE
) vk_code
,
533 (BYTE
) MapVirtualKey (vk_code
, 0),
534 KEYEVENTF_EXTENDEDKEY
| 0, 0);
535 keybd_event ((BYTE
) vk_code
,
536 (BYTE
) MapVirtualKey (vk_code
, 0),
537 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
538 cur_state
= !cur_state
;
544 /* Mouse position hook. */
546 w32_console_mouse_position (FRAME_PTR
*f
,
548 Lisp_Object
*bar_window
,
549 enum scroll_bar_part
*part
,
561 SELECTED_FRAME ()->mouse_moved
= 0;
563 XSETINT (*x
, movement_pos
.X
);
564 XSETINT (*y
, movement_pos
.Y
);
565 *time
= movement_time
;
570 /* Remember mouse motion and notify emacs. */
572 mouse_moved_to (int x
, int y
)
574 /* If we're in the same place, ignore it */
575 if (x
!= movement_pos
.X
|| y
!= movement_pos
.Y
)
577 SELECTED_FRAME ()->mouse_moved
= 1;
580 movement_time
= GetTickCount ();
584 /* Consoles return button bits in a strange order:
585 least significant - Leftmost button
586 next - Rightmost button
590 Assume emacs likes three button mice, so
594 Others increase from there. */
596 #define NUM_TRANSLATED_MOUSE_BUTTONS 3
597 static int emacs_button_translation
[NUM_TRANSLATED_MOUSE_BUTTONS
] =
603 do_mouse_event (MOUSE_EVENT_RECORD
*event
,
604 struct input_event
*emacs_ev
)
606 static DWORD button_state
= 0;
607 DWORD but_change
, mask
;
610 if (event
->dwEventFlags
== MOUSE_MOVED
)
612 /* For movement events we just note that the mouse has moved
613 so that emacs will generate drag events. */
614 mouse_moved_to (event
->dwMousePosition
.X
, event
->dwMousePosition
.Y
);
618 /* It looks like the console code sends us a mouse event with
619 dwButtonState == 0 when a window is activated. Ignore this case. */
620 if (event
->dwButtonState
== button_state
)
623 emacs_ev
->kind
= MOUSE_CLICK_EVENT
;
625 /* Find out what button has changed state since the last button event. */
626 but_change
= button_state
^ event
->dwButtonState
;
628 for (i
= 0; mask
; i
++, mask
<<= 1)
629 if (but_change
& mask
)
631 if (i
< NUM_TRANSLATED_MOUSE_BUTTONS
)
632 emacs_ev
->code
= emacs_button_translation
[i
];
638 button_state
= event
->dwButtonState
;
639 emacs_ev
->timestamp
= GetTickCount ();
640 emacs_ev
->modifiers
= w32_kbd_mods_to_emacs (event
->dwControlKeyState
, 0) |
641 ((event
->dwButtonState
& mask
) ? down_modifier
: up_modifier
);
643 XSETFASTINT (emacs_ev
->x
, event
->dwMousePosition
.X
);
644 XSETFASTINT (emacs_ev
->y
, event
->dwMousePosition
.Y
);
645 /* for Mule 2.2 (Based on Emacs 19.28 */
647 XSET (emacs_ev
->frame_or_window
, Lisp_Frame
, get_frame ());
649 XSETFRAME (emacs_ev
->frame_or_window
, get_frame ());
656 resize_event (WINDOW_BUFFER_SIZE_RECORD
*event
)
658 FRAME_PTR f
= get_frame ();
660 change_frame_size (f
, event
->dwSize
.Y
, event
->dwSize
.X
, 0, 1, 0);
661 SET_FRAME_GARBAGED (f
);
665 maybe_generate_resize_event (void)
667 CONSOLE_SCREEN_BUFFER_INFO info
;
668 FRAME_PTR f
= get_frame ();
670 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE
), &info
);
672 /* It is okay to call this unconditionally, since it will do nothing
673 if the size hasn't actually changed. */
674 change_frame_size (f
,
675 1 + info
.srWindow
.Bottom
- info
.srWindow
.Top
,
676 1 + info
.srWindow
.Right
- info
.srWindow
.Left
,
681 w32_console_read_socket (struct terminal
*terminal
,
683 struct input_event
*hold_quit
)
685 BOOL no_events
= TRUE
;
686 int nev
, ret
= 0, add
;
689 if (interrupt_input_blocked
)
691 interrupt_input_pending
= 1;
695 interrupt_input_pending
= 0;
700 nev
= fill_queue (0);
703 /* If nev == -1, there was some kind of error
704 If nev == 0 then waitp must be zero and no events were available
712 struct input_event inev
;
715 inev
.kind
= NO_EVENT
;
718 switch (queue_ptr
->EventType
)
721 add
= key_event (&queue_ptr
->Event
.KeyEvent
, &inev
, &isdead
);
722 if (add
== -1) /* 95.7.25 by himi */
728 kbd_buffer_store_event_hold (&inev
, hold_quit
);
732 add
= do_mouse_event (&queue_ptr
->Event
.MouseEvent
, &inev
);
734 kbd_buffer_store_event_hold (&inev
, hold_quit
);
737 case WINDOW_BUFFER_SIZE_EVENT
:
738 if (w32_use_full_screen_buffer
)
739 resize_event (&queue_ptr
->Event
.WindowBufferSizeEvent
);
744 /* Internal event types, ignored. */
752 if (ret
> 0 || expected
== 0)
756 /* We don't get told about changes in the window size (only the buffer
757 size, which we no longer care about), so we have to check it
759 if (!w32_use_full_screen_buffer
)
760 maybe_generate_resize_event ();