1 /* Input event support for Emacs on the Microsoft W32 API.
2 Copyright (C) 1992, 1993, 1995, 2001, 2002, 2003, 2004, 2005, 2006,
3 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22 Adapted from ntkbd.c by Tim Fleehart
38 #include "dispextern.h"
39 #include "blockinput.h"
40 #include "termhooks.h"
44 /* stdin, from ntterm */
45 extern HANDLE keyboard_handle
;
47 /* Info for last mouse motion */
48 static COORD movement_pos
;
49 static DWORD movement_time
;
52 extern void reinvoke_input_signal (void);
54 extern unsigned int map_keypad_keys (unsigned int, unsigned int);
56 extern unsigned int w32_key_to_modifier (int key
);
59 #define EVENT_QUEUE_SIZE 50
60 static INPUT_RECORD event_queue
[EVENT_QUEUE_SIZE
];
61 static INPUT_RECORD
*queue_ptr
= event_queue
, *queue_end
= event_queue
;
63 /* Temporarily store lead byte of DBCS input sequences. */
64 static char dbcs_lead
= 0;
67 fill_queue (BOOL block
)
72 if (queue_ptr
< queue_end
)
73 return queue_end
-queue_ptr
;
77 /* Check to see if there are some events to read before we try
78 because we can't block. */
79 if (!GetNumberOfConsoleInputEvents (keyboard_handle
, &events_waiting
))
81 if (events_waiting
== 0)
85 rc
= ReadConsoleInput (keyboard_handle
, event_queue
, EVENT_QUEUE_SIZE
,
89 queue_ptr
= event_queue
;
90 queue_end
= event_queue
+ events_waiting
;
91 return (int) events_waiting
;
94 /* In a generic, multi-frame world this should take a console handle
95 and return the frame for it
97 Right now, there's only one frame so return it. */
101 return SELECTED_FRAME ();
104 /* Translate console modifiers to emacs modifiers.
105 German keyboard support (Kai Morgan Zeise 2/18/95). */
107 w32_kbd_mods_to_emacs (DWORD mods
, WORD key
)
111 /* If we recognize right-alt and left-ctrl as AltGr, and it has been
112 pressed, first remove those modifiers. */
113 if (!NILP (Vw32_recognize_altgr
)
114 && (mods
& (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
))
115 == (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
))
116 mods
&= ~ (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
);
118 if (mods
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
119 retval
= ((NILP (Vw32_alt_is_meta
)) ? alt_modifier
: meta_modifier
);
121 if (mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
123 retval
|= ctrl_modifier
;
124 if ((mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
125 == (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
126 retval
|= meta_modifier
;
129 if (mods
& LEFT_WIN_PRESSED
)
130 retval
|= w32_key_to_modifier (VK_LWIN
);
131 if (mods
& RIGHT_WIN_PRESSED
)
132 retval
|= w32_key_to_modifier (VK_RWIN
);
133 if (mods
& APPS_PRESSED
)
134 retval
|= w32_key_to_modifier (VK_APPS
);
135 if (mods
& SCROLLLOCK_ON
)
136 retval
|= w32_key_to_modifier (VK_SCROLL
);
138 /* Just in case someone wanted the original behavior, make it
139 optional by setting w32-capslock-is-shiftlock to t. */
140 if (NILP (Vw32_capslock_is_shiftlock
)
141 /* Keys that should _not_ be affected by CapsLock. */
142 && ( (key
== VK_BACK
)
145 || (key
== VK_RETURN
)
146 || (key
== VK_ESCAPE
)
147 || ((key
>= VK_SPACE
) && (key
<= VK_HELP
))
148 || ((key
>= VK_NUMPAD0
) && (key
<= VK_F24
))
149 || ((key
>= VK_NUMPAD_CLEAR
) && (key
<= VK_NUMPAD_DELETE
))
152 /* Only consider shift state. */
153 if ((mods
& SHIFT_PRESSED
) != 0)
154 retval
|= shift_modifier
;
158 /* Ignore CapsLock state if not enabled. */
159 if (NILP (Vw32_enable_caps_lock
))
160 mods
&= ~CAPSLOCK_ON
;
161 if ((mods
& (SHIFT_PRESSED
| CAPSLOCK_ON
)) != 0)
162 retval
|= shift_modifier
;
169 /* Return nonzero if the virtual key is a dead key. */
171 is_dead_key (int wparam
)
173 unsigned int code
= MapVirtualKey (wparam
, 2);
175 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
176 return (code
& 0x80008000) ? 1 : 0;
180 /* The return code indicates key code size. */
182 w32_kbd_patch_key (KEY_EVENT_RECORD
*event
)
184 unsigned int key_code
= event
->wVirtualKeyCode
;
185 unsigned int mods
= event
->dwControlKeyState
;
187 static BYTE ansi_code
[4];
188 static int isdead
= 0;
192 event
->uChar
.AsciiChar
= ansi_code
[2];
196 if (event
->uChar
.AsciiChar
!= 0)
199 memset (keystate
, 0, sizeof (keystate
));
200 keystate
[key_code
] = 0x80;
201 if (mods
& SHIFT_PRESSED
)
202 keystate
[VK_SHIFT
] = 0x80;
203 if (mods
& CAPSLOCK_ON
)
204 keystate
[VK_CAPITAL
] = 1;
205 /* If we recognize right-alt and left-ctrl as AltGr, set the key
206 states accordingly before invoking ToAscii. */
207 if (!NILP (Vw32_recognize_altgr
)
208 && (mods
& LEFT_CTRL_PRESSED
) && (mods
& RIGHT_ALT_PRESSED
))
210 keystate
[VK_CONTROL
] = 0x80;
211 keystate
[VK_LCONTROL
] = 0x80;
212 keystate
[VK_MENU
] = 0x80;
213 keystate
[VK_RMENU
] = 0x80;
217 /* Because of an OS bug, ToAscii corrupts the stack when called to
218 convert a dead key in console mode on NT4. Unfortunately, trying
219 to check for dead keys using MapVirtualKey doesn't work either -
220 these functions apparently use internal information about keyboard
221 layout which doesn't get properly updated in console programs when
222 changing layout (though apparently it gets partly updated,
223 otherwise ToAscii wouldn't crash). */
224 if (is_dead_key (event
->wVirtualKeyCode
))
228 /* On NT, call ToUnicode instead and then convert to the current
229 locale's default codepage. */
230 if (os_subtype
== OS_NT
)
234 isdead
= ToUnicode (event
->wVirtualKeyCode
, event
->wVirtualScanCode
,
235 keystate
, buf
, 128, 0);
241 event
->uChar
.UnicodeChar
= buf
[isdead
- 1];
243 GetLocaleInfo (GetThreadLocale (),
244 LOCALE_IDEFAULTANSICODEPAGE
, cp
, 20);
246 isdead
= WideCharToMultiByte (cpId
, 0, buf
, isdead
,
247 ansi_code
, 4, NULL
, NULL
);
254 isdead
= ToAscii (event
->wVirtualKeyCode
, event
->wVirtualScanCode
,
255 keystate
, (LPWORD
) ansi_code
, 0);
260 event
->uChar
.AsciiChar
= ansi_code
[0];
265 extern const char *const lispy_function_keys
[];
267 static int faked_key
= 0;
269 /* return code -1 means that event_queue_ptr won't be incremented.
270 In other word, this event makes two key codes. (by himi) */
272 key_event (KEY_EVENT_RECORD
*event
, struct input_event
*emacs_ev
, int *isdead
)
274 static int mod_key_state
= 0;
279 /* Skip key-up events. */
280 if (!event
->bKeyDown
)
282 switch (event
->wVirtualKeyCode
)
285 mod_key_state
&= ~LEFT_WIN_PRESSED
;
288 mod_key_state
&= ~RIGHT_WIN_PRESSED
;
291 mod_key_state
&= ~APPS_PRESSED
;
297 /* Ignore keystrokes we fake ourself; see below. */
298 if (faked_key
== event
->wVirtualKeyCode
)
304 /* To make it easier to debug this code, ignore modifier keys! */
305 switch (event
->wVirtualKeyCode
)
308 if (NILP (Vw32_pass_lwindow_to_system
))
310 /* Prevent system from acting on keyup (which opens the Start
311 menu if no other key was pressed) by simulating a press of
312 Space which we will ignore. */
313 if ((mod_key_state
& LEFT_WIN_PRESSED
) == 0)
315 if (NUMBERP (Vw32_phantom_key_code
))
316 faked_key
= XUINT (Vw32_phantom_key_code
) & 255;
318 faked_key
= VK_SPACE
;
319 keybd_event (faked_key
, (BYTE
) MapVirtualKey (faked_key
, 0), 0, 0);
322 mod_key_state
|= LEFT_WIN_PRESSED
;
323 if (!NILP (Vw32_lwindow_modifier
))
327 if (NILP (Vw32_pass_rwindow_to_system
))
329 if ((mod_key_state
& RIGHT_WIN_PRESSED
) == 0)
331 if (NUMBERP (Vw32_phantom_key_code
))
332 faked_key
= XUINT (Vw32_phantom_key_code
) & 255;
334 faked_key
= VK_SPACE
;
335 keybd_event (faked_key
, (BYTE
) MapVirtualKey (faked_key
, 0), 0, 0);
338 mod_key_state
|= RIGHT_WIN_PRESSED
;
339 if (!NILP (Vw32_rwindow_modifier
))
343 mod_key_state
|= APPS_PRESSED
;
344 if (!NILP (Vw32_apps_modifier
))
348 /* Decide whether to treat as modifier or function key. */
349 if (NILP (Vw32_enable_caps_lock
))
350 goto disable_lock_key
;
353 /* Decide whether to treat as modifier or function key. */
354 if (NILP (Vw32_enable_num_lock
))
355 goto disable_lock_key
;
358 /* Decide whether to treat as modifier or function key. */
359 if (NILP (Vw32_scroll_lock_modifier
))
360 goto disable_lock_key
;
363 /* Ensure the appropriate lock key state is off (and the
364 indicator light as well). */
365 wParam
= event
->wVirtualKeyCode
;
366 if (GetAsyncKeyState (wParam
) & 0x8000)
368 /* Fake another press of the relevant key. Apparently, this
369 really is the only way to turn off the indicator. */
371 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
372 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
373 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
374 KEYEVENTF_EXTENDEDKEY
| 0, 0);
375 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
376 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
384 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
385 which is confusing for purposes of key binding; convert
386 VK_CANCEL events into VK_PAUSE events. */
387 event
->wVirtualKeyCode
= VK_PAUSE
;
390 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
391 for purposes of key binding; convert these back into
392 VK_NUMLOCK events, at least when we want to see NumLock key
393 presses. (Note that there is never any possibility that
394 VK_PAUSE with Ctrl really is C-Pause as per above.) */
395 if (NILP (Vw32_enable_num_lock
)
396 && (event
->dwControlKeyState
397 & (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)) != 0)
398 event
->wVirtualKeyCode
= VK_NUMLOCK
;
402 /* Recognize state of Windows and Apps keys. */
403 event
->dwControlKeyState
|= mod_key_state
;
405 /* Distinguish numeric keypad keys from extended keys. */
406 event
->wVirtualKeyCode
=
407 map_keypad_keys (event
->wVirtualKeyCode
,
408 (event
->dwControlKeyState
& ENHANCED_KEY
));
410 if (lispy_function_keys
[event
->wVirtualKeyCode
] == 0)
412 if (!NILP (Vw32_recognize_altgr
)
413 && (event
->dwControlKeyState
& LEFT_CTRL_PRESSED
)
414 && (event
->dwControlKeyState
& RIGHT_ALT_PRESSED
))
416 /* Don't try to interpret AltGr key chords; ToAscii seems not
417 to process them correctly. */
419 /* Handle key chords including any modifiers other than shift
420 directly, in order to preserve as much modifier information as
422 else if (event
->dwControlKeyState
423 & ( RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
424 | RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
425 | (!NILP (Vw32_lwindow_modifier
) ? LEFT_WIN_PRESSED
: 0)
426 | (!NILP (Vw32_rwindow_modifier
) ? RIGHT_WIN_PRESSED
: 0)
427 | (!NILP (Vw32_apps_modifier
) ? APPS_PRESSED
: 0)
428 | (!NILP (Vw32_scroll_lock_modifier
) ? SCROLLLOCK_ON
: 0)))
430 /* Don't translate modified alphabetic keystrokes, so the user
431 doesn't need to constantly switch layout to type control or
432 meta keystrokes when the normal layout translates
433 alphabetic characters to non-ascii characters. */
434 if ('A' <= event
->wVirtualKeyCode
&& event
->wVirtualKeyCode
<= 'Z')
436 event
->uChar
.AsciiChar
= event
->wVirtualKeyCode
;
437 if ((event
->dwControlKeyState
& SHIFT_PRESSED
) == 0)
438 event
->uChar
.AsciiChar
+= ('a' - 'A');
440 /* Try to handle unrecognized keystrokes by determining the
441 base character (ie. translating the base key plus shift
443 else if (event
->uChar
.AsciiChar
== 0)
444 w32_kbd_patch_key (event
);
447 if (event
->uChar
.AsciiChar
== 0)
449 emacs_ev
->kind
= NO_EVENT
;
452 else if (event
->uChar
.AsciiChar
> 0)
454 emacs_ev
->kind
= ASCII_KEYSTROKE_EVENT
;
455 emacs_ev
->code
= event
->uChar
.AsciiChar
;
457 else if (event
->uChar
.UnicodeChar
> 0)
459 emacs_ev
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
460 emacs_ev
->code
= event
->uChar
.UnicodeChar
;
464 /* Fallback for non-Unicode versions of Windows. */
470 /* Get the codepage to interpret this key with. */
471 GetLocaleInfo (GetThreadLocale (),
472 LOCALE_IDEFAULTANSICODEPAGE
, cp
, 20);
476 dbcs
[1] = event
->uChar
.AsciiChar
;
480 if (!MultiByteToWideChar (cpId
, 0, dbcs
, 2, &code
, 1))
483 DebPrint (("Invalid DBCS sequence: %d %d\n",
485 emacs_ev
->kind
= NO_EVENT
;
488 else if (IsDBCSLeadByteEx (cpId
, dbcs
[1]))
491 emacs_ev
->kind
= NO_EVENT
;
495 if (!MultiByteToWideChar (cpId
, 0, &dbcs
[1], 1, &code
, 1))
498 DebPrint (("Invalid character: %d\n", dbcs
[1]));
499 emacs_ev
->kind
= NO_EVENT
;
502 emacs_ev
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
503 emacs_ev
->code
= code
;
508 emacs_ev
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
509 emacs_ev
->code
= event
->wVirtualKeyCode
;
512 XSETFRAME (emacs_ev
->frame_or_window
, get_frame ());
513 emacs_ev
->modifiers
= w32_kbd_mods_to_emacs (event
->dwControlKeyState
,
514 event
->wVirtualKeyCode
);
515 emacs_ev
->timestamp
= GetTickCount ();
520 w32_console_toggle_lock_key (int vk_code
, Lisp_Object new_state
)
522 int cur_state
= (GetKeyState (vk_code
) & 1);
525 || (NUMBERP (new_state
)
526 && ((XUINT (new_state
)) & 1) != cur_state
))
530 keybd_event ((BYTE
) vk_code
,
531 (BYTE
) MapVirtualKey (vk_code
, 0),
532 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
533 keybd_event ((BYTE
) vk_code
,
534 (BYTE
) MapVirtualKey (vk_code
, 0),
535 KEYEVENTF_EXTENDEDKEY
| 0, 0);
536 keybd_event ((BYTE
) vk_code
,
537 (BYTE
) MapVirtualKey (vk_code
, 0),
538 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
539 cur_state
= !cur_state
;
545 /* Mouse position hook. */
547 w32_console_mouse_position (FRAME_PTR
*f
,
549 Lisp_Object
*bar_window
,
550 enum scroll_bar_part
*part
,
562 SELECTED_FRAME ()->mouse_moved
= 0;
564 XSETINT (*x
, movement_pos
.X
);
565 XSETINT (*y
, movement_pos
.Y
);
566 *time
= movement_time
;
571 /* Remember mouse motion and notify emacs. */
573 mouse_moved_to (int x
, int y
)
575 /* If we're in the same place, ignore it */
576 if (x
!= movement_pos
.X
|| y
!= movement_pos
.Y
)
578 SELECTED_FRAME ()->mouse_moved
= 1;
581 movement_time
= GetTickCount ();
585 /* Consoles return button bits in a strange order:
586 least significant - Leftmost button
587 next - Rightmost button
591 Assume emacs likes three button mice, so
595 Others increase from there. */
597 #define NUM_TRANSLATED_MOUSE_BUTTONS 3
598 static int emacs_button_translation
[NUM_TRANSLATED_MOUSE_BUTTONS
] =
604 do_mouse_event (MOUSE_EVENT_RECORD
*event
,
605 struct input_event
*emacs_ev
)
607 static DWORD button_state
= 0;
608 DWORD but_change
, mask
;
611 if (event
->dwEventFlags
== MOUSE_MOVED
)
613 /* For movement events we just note that the mouse has moved
614 so that emacs will generate drag events. */
615 mouse_moved_to (event
->dwMousePosition
.X
, event
->dwMousePosition
.Y
);
619 /* It looks like the console code sends us a mouse event with
620 dwButtonState == 0 when a window is activated. Ignore this case. */
621 if (event
->dwButtonState
== button_state
)
624 emacs_ev
->kind
= MOUSE_CLICK_EVENT
;
626 /* Find out what button has changed state since the last button event. */
627 but_change
= button_state
^ event
->dwButtonState
;
629 for (i
= 0; mask
; i
++, mask
<<= 1)
630 if (but_change
& mask
)
632 if (i
< NUM_TRANSLATED_MOUSE_BUTTONS
)
633 emacs_ev
->code
= emacs_button_translation
[i
];
639 button_state
= event
->dwButtonState
;
640 emacs_ev
->timestamp
= GetTickCount ();
641 emacs_ev
->modifiers
= w32_kbd_mods_to_emacs (event
->dwControlKeyState
, 0) |
642 ((event
->dwButtonState
& mask
) ? down_modifier
: up_modifier
);
644 XSETFASTINT (emacs_ev
->x
, event
->dwMousePosition
.X
);
645 XSETFASTINT (emacs_ev
->y
, event
->dwMousePosition
.Y
);
646 /* for Mule 2.2 (Based on Emacs 19.28 */
648 XSET (emacs_ev
->frame_or_window
, Lisp_Frame
, get_frame ());
650 XSETFRAME (emacs_ev
->frame_or_window
, get_frame ());
657 resize_event (WINDOW_BUFFER_SIZE_RECORD
*event
)
659 FRAME_PTR f
= get_frame ();
661 change_frame_size (f
, event
->dwSize
.Y
, event
->dwSize
.X
, 0, 1, 0);
662 SET_FRAME_GARBAGED (f
);
666 maybe_generate_resize_event (void)
668 CONSOLE_SCREEN_BUFFER_INFO info
;
669 FRAME_PTR f
= get_frame ();
671 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE
), &info
);
673 /* It is okay to call this unconditionally, since it will do nothing
674 if the size hasn't actually changed. */
675 change_frame_size (f
,
676 1 + info
.srWindow
.Bottom
- info
.srWindow
.Top
,
677 1 + info
.srWindow
.Right
- info
.srWindow
.Left
,
682 w32_console_read_socket (struct terminal
*terminal
,
684 struct input_event
*hold_quit
)
686 BOOL no_events
= TRUE
;
687 int nev
, ret
= 0, add
;
690 if (interrupt_input_blocked
)
692 interrupt_input_pending
= 1;
696 interrupt_input_pending
= 0;
701 nev
= fill_queue (0);
704 /* If nev == -1, there was some kind of error
705 If nev == 0 then waitp must be zero and no events were available
713 struct input_event inev
;
716 inev
.kind
= NO_EVENT
;
719 switch (queue_ptr
->EventType
)
722 add
= key_event (&queue_ptr
->Event
.KeyEvent
, &inev
, &isdead
);
723 if (add
== -1) /* 95.7.25 by himi */
729 kbd_buffer_store_event_hold (&inev
, hold_quit
);
733 add
= do_mouse_event (&queue_ptr
->Event
.MouseEvent
, &inev
);
735 kbd_buffer_store_event_hold (&inev
, hold_quit
);
738 case WINDOW_BUFFER_SIZE_EVENT
:
739 if (w32_use_full_screen_buffer
)
740 resize_event (&queue_ptr
->Event
.WindowBufferSizeEvent
);
745 /* Internal event types, ignored. */
753 if (ret
> 0 || expected
== 0)
757 /* We don't get told about changes in the window size (only the buffer
758 size, which we no longer care about), so we have to check it
760 if (!w32_use_full_screen_buffer
)
761 maybe_generate_resize_event ();