1 /* Input event support for Emacs on the Microsoft Windows API.
2 Copyright (C) 1992-1993, 1995, 2001-2012 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
36 #include "dispextern.h"
38 #include "blockinput.h"
39 #include "termhooks.h"
45 /* stdin, from w32console.c */
46 extern HANDLE keyboard_handle
;
48 /* Info for last mouse motion */
49 static COORD movement_pos
;
50 static Time movement_time
;
53 extern unsigned int map_keypad_keys (unsigned int, unsigned int);
54 extern unsigned int w32_key_to_modifier (int key
);
57 #define EVENT_QUEUE_SIZE 50
58 static INPUT_RECORD event_queue
[EVENT_QUEUE_SIZE
];
59 static INPUT_RECORD
*queue_ptr
= event_queue
, *queue_end
= event_queue
;
61 /* Temporarily store lead byte of DBCS input sequences. */
62 static char dbcs_lead
= 0;
65 w32_read_console_input (HANDLE h
, INPUT_RECORD
*rec
, DWORD recsize
,
68 return (w32_console_unicode_input
69 ? ReadConsoleInputW (h
, rec
, recsize
, waiting
)
70 : ReadConsoleInputA (h
, rec
, recsize
, waiting
));
73 /* Set by w32_console_toggle_lock_key. */
77 fill_queue (BOOL block
)
82 if (queue_ptr
< queue_end
)
83 return queue_end
-queue_ptr
;
87 /* Check to see if there are some events to read before we try
88 because we can't block. */
89 if (!GetNumberOfConsoleInputEvents (keyboard_handle
, &events_waiting
))
91 if (events_waiting
== 0)
95 rc
= w32_read_console_input (keyboard_handle
, event_queue
, EVENT_QUEUE_SIZE
,
99 queue_ptr
= event_queue
;
100 queue_end
= event_queue
+ events_waiting
;
101 return (int) events_waiting
;
104 /* In a generic, multi-frame world this should take a console handle
105 and return the frame for it
107 Right now, there's only one frame so return it. */
111 return SELECTED_FRAME ();
114 /* Translate console modifiers to emacs modifiers.
115 German keyboard support (Kai Morgan Zeise 2/18/95). */
119 /* Return nonzero if the virtual key is a dead key. */
121 is_dead_key (int wparam
)
123 unsigned int code
= MapVirtualKey (wparam
, 2);
125 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
126 return (code
& 0x80008000) ? 1 : 0;
130 /* The return code indicates key code size. cpID is the codepage to
131 use for translation to Unicode; -1 means use the current console
135 /* return code -1 means that event_queue_ptr won't be incremented.
136 In other word, this event makes two key codes. (by himi) */
138 key_event (KEY_EVENT_RECORD
*event
, struct input_event
*emacs_ev
, int *isdead
)
140 static int mod_key_state
= 0;
145 /* Skip key-up events. */
146 if (!event
->bKeyDown
)
148 switch (event
->wVirtualKeyCode
)
151 mod_key_state
&= ~LEFT_WIN_PRESSED
;
154 mod_key_state
&= ~RIGHT_WIN_PRESSED
;
157 mod_key_state
&= ~APPS_PRESSED
;
163 /* Ignore keystrokes we fake ourself; see below. */
164 if (faked_key
== event
->wVirtualKeyCode
)
170 /* To make it easier to debug this code, ignore modifier keys! */
171 switch (event
->wVirtualKeyCode
)
174 if (NILP (Vw32_pass_lwindow_to_system
))
176 /* Prevent system from acting on keyup (which opens the Start
177 menu if no other key was pressed) by simulating a press of
178 Space which we will ignore. */
179 if ((mod_key_state
& LEFT_WIN_PRESSED
) == 0)
181 if (NUMBERP (Vw32_phantom_key_code
))
182 faked_key
= XUINT (Vw32_phantom_key_code
) & 255;
184 faked_key
= VK_SPACE
;
185 keybd_event (faked_key
, (BYTE
) MapVirtualKey (faked_key
, 0), 0, 0);
188 mod_key_state
|= LEFT_WIN_PRESSED
;
189 if (!NILP (Vw32_lwindow_modifier
))
193 if (NILP (Vw32_pass_rwindow_to_system
))
195 if ((mod_key_state
& RIGHT_WIN_PRESSED
) == 0)
197 if (NUMBERP (Vw32_phantom_key_code
))
198 faked_key
= XUINT (Vw32_phantom_key_code
) & 255;
200 faked_key
= VK_SPACE
;
201 keybd_event (faked_key
, (BYTE
) MapVirtualKey (faked_key
, 0), 0, 0);
204 mod_key_state
|= RIGHT_WIN_PRESSED
;
205 if (!NILP (Vw32_rwindow_modifier
))
209 mod_key_state
|= APPS_PRESSED
;
210 if (!NILP (Vw32_apps_modifier
))
214 /* Decide whether to treat as modifier or function key. */
215 if (NILP (Vw32_enable_caps_lock
))
216 goto disable_lock_key
;
219 /* Decide whether to treat as modifier or function key. */
220 if (NILP (Vw32_enable_num_lock
))
221 goto disable_lock_key
;
224 /* Decide whether to treat as modifier or function key. */
225 if (NILP (Vw32_scroll_lock_modifier
))
226 goto disable_lock_key
;
229 /* Ensure the appropriate lock key state is off (and the
230 indicator light as well). */
231 wParam
= event
->wVirtualKeyCode
;
232 if (GetAsyncKeyState (wParam
) & 0x8000)
234 /* Fake another press of the relevant key. Apparently, this
235 really is the only way to turn off the indicator. */
237 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
238 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
239 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
240 KEYEVENTF_EXTENDEDKEY
| 0, 0);
241 keybd_event ((BYTE
) wParam
, (BYTE
) MapVirtualKey (wParam
, 0),
242 KEYEVENTF_EXTENDEDKEY
| KEYEVENTF_KEYUP
, 0);
250 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
251 which is confusing for purposes of key binding; convert
252 VK_CANCEL events into VK_PAUSE events. */
253 event
->wVirtualKeyCode
= VK_PAUSE
;
256 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
257 for purposes of key binding; convert these back into
258 VK_NUMLOCK events, at least when we want to see NumLock key
259 presses. (Note that there is never any possibility that
260 VK_PAUSE with Ctrl really is C-Pause as per above.) */
261 if (NILP (Vw32_enable_num_lock
)
262 && (event
->dwControlKeyState
263 & (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
)) != 0)
264 event
->wVirtualKeyCode
= VK_NUMLOCK
;
268 /* Recognize state of Windows and Apps keys. */
269 event
->dwControlKeyState
|= mod_key_state
;
271 /* Distinguish numeric keypad keys from extended keys. */
272 event
->wVirtualKeyCode
=
273 map_keypad_keys (event
->wVirtualKeyCode
,
274 (event
->dwControlKeyState
& ENHANCED_KEY
));
276 if (lispy_function_keys
[event
->wVirtualKeyCode
] == 0)
278 if (!NILP (Vw32_recognize_altgr
)
279 && (event
->dwControlKeyState
& LEFT_CTRL_PRESSED
)
280 && (event
->dwControlKeyState
& RIGHT_ALT_PRESSED
))
282 /* Don't try to interpret AltGr key chords; ToAscii seems not
283 to process them correctly. */
285 /* Handle key chords including any modifiers other than shift
286 directly, in order to preserve as much modifier information as
288 else if (event
->dwControlKeyState
289 & ( RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
290 | RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
291 | (!NILP (Vw32_lwindow_modifier
) ? LEFT_WIN_PRESSED
: 0)
292 | (!NILP (Vw32_rwindow_modifier
) ? RIGHT_WIN_PRESSED
: 0)
293 | (!NILP (Vw32_apps_modifier
) ? APPS_PRESSED
: 0)
294 | (!NILP (Vw32_scroll_lock_modifier
) ? SCROLLLOCK_ON
: 0)))
296 /* Don't translate modified alphabetic keystrokes, so the user
297 doesn't need to constantly switch layout to type control or
298 meta keystrokes when the normal layout translates
299 alphabetic characters to non-ascii characters. */
300 if ('A' <= event
->wVirtualKeyCode
&& event
->wVirtualKeyCode
<= 'Z')
302 event
->uChar
.AsciiChar
= event
->wVirtualKeyCode
;
303 if ((event
->dwControlKeyState
& SHIFT_PRESSED
) == 0)
304 event
->uChar
.AsciiChar
+= ('a' - 'A');
306 /* Try to handle unrecognized keystrokes by determining the
307 base character (ie. translating the base key plus shift
309 else if (event
->uChar
.AsciiChar
== 0)
310 w32_kbd_patch_key (event
, -1);
313 if (event
->uChar
.AsciiChar
== 0)
315 emacs_ev
->kind
= NO_EVENT
;
318 else if (event
->uChar
.AsciiChar
> 0)
320 /* Pure ASCII characters < 128. */
321 emacs_ev
->kind
= ASCII_KEYSTROKE_EVENT
;
322 emacs_ev
->code
= event
->uChar
.AsciiChar
;
324 else if (event
->uChar
.UnicodeChar
> 0
325 && w32_console_unicode_input
)
327 /* Unicode codepoint; only valid if we are using Unicode
328 console input mode. */
329 emacs_ev
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
330 emacs_ev
->code
= event
->uChar
.UnicodeChar
;
334 /* Fallback handling of non-ASCII characters for non-Unicode
335 versions of Windows, and for non-Unicode input on NT
336 family of Windows. Only characters in the current
337 console codepage are supported by this fallback. */
342 /* Get the current console input codepage to interpret this
343 key with. Note that the system defaults for the OEM
344 codepage could have been changed by calling SetConsoleCP
345 or w32-set-console-codepage, so using GetLocaleInfo to
346 get LOCALE_IDEFAULTCODEPAGE is not TRT here. */
347 cpId
= GetConsoleCP ();
350 dbcs
[1] = event
->uChar
.AsciiChar
;
354 if (!MultiByteToWideChar (cpId
, 0, dbcs
, 2, &code
, 1))
357 DebPrint (("Invalid DBCS sequence: %d %d\n",
359 emacs_ev
->kind
= NO_EVENT
;
362 else if (IsDBCSLeadByteEx (cpId
, dbcs
[1]))
365 emacs_ev
->kind
= NO_EVENT
;
369 if (!MultiByteToWideChar (cpId
, 0, &dbcs
[1], 1, &code
, 1))
372 DebPrint (("Invalid character: %d\n", dbcs
[1]));
373 emacs_ev
->kind
= NO_EVENT
;
376 emacs_ev
->kind
= MULTIBYTE_CHAR_KEYSTROKE_EVENT
;
377 emacs_ev
->code
= code
;
382 /* Function keys and other non-character keys. */
383 emacs_ev
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
384 emacs_ev
->code
= event
->wVirtualKeyCode
;
387 XSETFRAME (emacs_ev
->frame_or_window
, get_frame ());
388 emacs_ev
->modifiers
= w32_kbd_mods_to_emacs (event
->dwControlKeyState
,
389 event
->wVirtualKeyCode
);
390 emacs_ev
->timestamp
= GetTickCount ();
394 /* Mouse position hook. */
396 w32_console_mouse_position (FRAME_PTR
*f
,
398 Lisp_Object
*bar_window
,
399 enum scroll_bar_part
*part
,
411 SELECTED_FRAME ()->mouse_moved
= 0;
413 XSETINT (*x
, movement_pos
.X
);
414 XSETINT (*y
, movement_pos
.Y
);
415 *time
= movement_time
;
420 /* Remember mouse motion and notify emacs. */
422 mouse_moved_to (int x
, int y
)
424 /* If we're in the same place, ignore it. */
425 if (x
!= movement_pos
.X
|| y
!= movement_pos
.Y
)
427 SELECTED_FRAME ()->mouse_moved
= 1;
430 movement_time
= GetTickCount ();
434 /* Consoles return button bits in a strange order:
435 least significant - Leftmost button
436 next - Rightmost button
440 Assume emacs likes three button mice, so
444 Others increase from there. */
446 #define NUM_TRANSLATED_MOUSE_BUTTONS 3
447 static int emacs_button_translation
[NUM_TRANSLATED_MOUSE_BUTTONS
] =
453 do_mouse_event (MOUSE_EVENT_RECORD
*event
,
454 struct input_event
*emacs_ev
)
456 static DWORD button_state
= 0;
457 static Lisp_Object last_mouse_window
;
458 DWORD but_change
, mask
;
461 if (event
->dwEventFlags
== MOUSE_MOVED
)
463 FRAME_PTR f
= SELECTED_FRAME ();
464 Mouse_HLInfo
*hlinfo
= MOUSE_HL_INFO (f
);
465 int mx
= event
->dwMousePosition
.X
, my
= event
->dwMousePosition
.Y
;
467 mouse_moved_to (mx
, my
);
471 if (hlinfo
->mouse_face_hidden
)
473 hlinfo
->mouse_face_hidden
= 0;
474 clear_mouse_face (hlinfo
);
477 /* Generate SELECT_WINDOW_EVENTs when needed. */
478 if (!NILP (Vmouse_autoselect_window
))
480 Lisp_Object mouse_window
= window_from_coordinates (f
, mx
, my
,
482 /* A window will be selected only when it is not
483 selected now, and the last mouse movement event was
484 not in it. A minibuffer window will be selected iff
486 if (WINDOWP (mouse_window
)
487 && !EQ (mouse_window
, last_mouse_window
)
488 && !EQ (mouse_window
, selected_window
))
490 struct input_event event
;
493 event
.kind
= SELECT_WINDOW_EVENT
;
494 event
.frame_or_window
= mouse_window
;
496 event
.timestamp
= movement_time
;
497 kbd_buffer_store_event (&event
);
499 last_mouse_window
= mouse_window
;
502 last_mouse_window
= Qnil
;
504 previous_help_echo_string
= help_echo_string
;
505 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
507 note_mouse_highlight (f
, mx
, my
);
508 /* If the contents of the global variable help_echo has
509 changed (inside note_mouse_highlight), generate a HELP_EVENT. */
510 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
511 gen_help_event (help_echo_string
, selected_frame
, help_echo_window
,
512 help_echo_object
, help_echo_pos
);
517 /* It looks like the console code sends us a mouse event with
518 dwButtonState == 0 when a window is activated. Ignore this case. */
519 if (event
->dwButtonState
== button_state
)
522 emacs_ev
->kind
= MOUSE_CLICK_EVENT
;
524 /* Find out what button has changed state since the last button event. */
525 but_change
= button_state
^ event
->dwButtonState
;
527 for (i
= 0; mask
; i
++, mask
<<= 1)
528 if (but_change
& mask
)
530 if (i
< NUM_TRANSLATED_MOUSE_BUTTONS
)
531 emacs_ev
->code
= emacs_button_translation
[i
];
537 button_state
= event
->dwButtonState
;
538 emacs_ev
->timestamp
= GetTickCount ();
539 emacs_ev
->modifiers
= w32_kbd_mods_to_emacs (event
->dwControlKeyState
, 0) |
540 ((event
->dwButtonState
& mask
) ? down_modifier
: up_modifier
);
542 XSETFASTINT (emacs_ev
->x
, event
->dwMousePosition
.X
);
543 XSETFASTINT (emacs_ev
->y
, event
->dwMousePosition
.Y
);
544 /* for Mule 2.2 (Based on Emacs 19.28 */
546 XSET (emacs_ev
->frame_or_window
, Lisp_Frame
, get_frame ());
548 XSETFRAME (emacs_ev
->frame_or_window
, get_frame ());
555 resize_event (WINDOW_BUFFER_SIZE_RECORD
*event
)
557 FRAME_PTR f
= get_frame ();
559 change_frame_size (f
, event
->dwSize
.Y
, event
->dwSize
.X
, 0, 1, 0);
560 SET_FRAME_GARBAGED (f
);
564 maybe_generate_resize_event (void)
566 CONSOLE_SCREEN_BUFFER_INFO info
;
567 FRAME_PTR f
= get_frame ();
569 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE
), &info
);
571 /* It is okay to call this unconditionally, since it will do nothing
572 if the size hasn't actually changed. */
573 change_frame_size (f
,
574 1 + info
.srWindow
.Bottom
- info
.srWindow
.Top
,
575 1 + info
.srWindow
.Right
- info
.srWindow
.Left
,
579 /* Here's an overview of how Emacs input works in non-GUI sessions on
580 MS-Windows. (For description of the GUI input, see the commentary
581 before w32_msg_pump in w32fns.c.)
583 When Emacs is idle, it loops inside wait_reading_process_output,
584 calling pselect periodically to check whether any input is
585 available. On Windows, pselect is redirected to sys_select, which
586 uses MsgWaitForMultipleObjects to wait for input, either from the
587 keyboard or from any of the Emacs subprocesses. In addition,
588 MsgWaitForMultipleObjects wakes up when some Windows message is
589 posted to the input queue of the Emacs's main thread (which is the
590 thread in which sys_select runs).
592 When the Emacs's console window has focus, Windows sends input
593 events that originate from the keyboard or the mouse; these events
594 wake up MsgWaitForMultipleObjects, which reports that input is
595 available. Emacs then calls w32_console_read_socket, below, to
596 read the input. w32_console_read_socket uses
597 GetNumberOfConsoleInputEvents and ReadConsoleInput to peek at and
598 read the console input events.
600 One type of non-keyboard input event that gets reported as input
601 available is due to the Emacs's console window receiving focus.
602 When that happens, Emacs gets the FOCUS_EVENT event and sys_select
603 reports some input; however, w32_console_read_socket ignores such
604 events when called to read them.
606 Note that any other Windows message sent to the main thread will
607 also wake up MsgWaitForMultipleObjects. These messages get
608 immediately dispatched to their destinations by calling
609 drain_message_queue. */
612 w32_console_read_socket (struct terminal
*terminal
,
613 struct input_event
*hold_quit
)
622 nev
= fill_queue (0);
625 /* If nev == -1, there was some kind of error
626 If nev == 0 then waitp must be zero and no events were available
633 struct input_event inev
;
636 inev
.kind
= NO_EVENT
;
639 switch (queue_ptr
->EventType
)
642 add
= key_event (&queue_ptr
->Event
.KeyEvent
, &inev
, &isdead
);
643 if (add
== -1) /* 95.7.25 by himi */
649 kbd_buffer_store_event_hold (&inev
, hold_quit
);
653 add
= do_mouse_event (&queue_ptr
->Event
.MouseEvent
, &inev
);
655 kbd_buffer_store_event_hold (&inev
, hold_quit
);
658 case WINDOW_BUFFER_SIZE_EVENT
:
659 if (w32_use_full_screen_buffer
)
660 resize_event (&queue_ptr
->Event
.WindowBufferSizeEvent
);
665 /* Internal event types, ignored. */
674 /* We don't get told about changes in the window size (only the buffer
675 size, which we no longer care about), so we have to check it
677 if (!w32_use_full_screen_buffer
)
678 maybe_generate_resize_event ();