Improve accessibility of window dividers. (Bug#20183)
[emacs.git] / src / w32inevt.c
blobea2db26a60ef4a2882b333799603ceb2eeeb8e32
1 /* Input event support for Emacs on the Microsoft Windows API.
2 Copyright (C) 1992-1993, 1995, 2001-2015 Free Software Foundation,
3 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/>. */
21 Drew Bliss 01-Oct-93
22 Adapted from ntkbd.c by Tim Fleehart
26 #include <config.h>
27 #include <stdio.h>
28 #include <windows.h>
30 #ifndef MOUSE_MOVED
31 #define MOUSE_MOVED 1
32 #endif
33 #ifndef MOUSE_HWHEELED
34 #define MOUSE_HWHEELED 8
35 #endif
37 #include "lisp.h"
38 #include "keyboard.h"
39 #include "frame.h"
40 #include "dispextern.h"
41 #include "window.h"
42 #include "blockinput.h"
43 #include "termhooks.h"
44 #include "termchar.h"
45 #include "w32heap.h"
46 #include "w32term.h"
47 #include "w32inevt.h"
49 /* stdin, from w32console.c */
50 extern HANDLE keyboard_handle;
52 /* Info for last mouse motion */
53 static COORD movement_pos;
54 static Time movement_time;
56 /* from w32fns.c */
57 extern unsigned int map_keypad_keys (unsigned int, unsigned int);
58 extern unsigned int w32_key_to_modifier (int key);
60 /* Event queue */
61 #define EVENT_QUEUE_SIZE 50
62 static INPUT_RECORD event_queue[EVENT_QUEUE_SIZE];
63 static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue;
65 /* Temporarily store lead byte of DBCS input sequences. */
66 static char dbcs_lead = 0;
68 static inline BOOL
69 w32_read_console_input (HANDLE h, INPUT_RECORD *rec, DWORD recsize,
70 DWORD *waiting)
72 return (w32_console_unicode_input
73 ? ReadConsoleInputW (h, rec, recsize, waiting)
74 : ReadConsoleInputA (h, rec, recsize, waiting));
77 /* Set by w32_console_toggle_lock_key. */
78 int faked_key;
80 static int
81 fill_queue (BOOL block)
83 BOOL rc;
84 DWORD events_waiting;
86 if (queue_ptr < queue_end)
87 return queue_end-queue_ptr;
89 if (!block)
91 /* Check to see if there are some events to read before we try
92 because we can't block. */
93 if (!GetNumberOfConsoleInputEvents (keyboard_handle, &events_waiting))
94 return -1;
95 if (events_waiting == 0)
96 return 0;
99 rc = w32_read_console_input (keyboard_handle, event_queue, EVENT_QUEUE_SIZE,
100 &events_waiting);
101 if (!rc)
102 return -1;
103 queue_ptr = event_queue;
104 queue_end = event_queue + events_waiting;
105 return (int) events_waiting;
108 /* In a generic, multi-frame world this should take a console handle
109 and return the frame for it.
111 Right now, there's only one frame so return it. */
112 static struct frame *
113 get_frame (void)
115 return SELECTED_FRAME ();
118 /* Translate console modifiers to emacs modifiers.
119 German keyboard support (Kai Morgan Zeise 2/18/95). */
122 #if 0
123 /* Return nonzero if the virtual key is a dead key. */
124 static int
125 is_dead_key (int wparam)
127 unsigned int code = MapVirtualKey (wparam, 2);
129 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
130 return (code & 0x80008000) ? 1 : 0;
132 #endif
134 /* The return code indicates key code size. cpID is the codepage to
135 use for translation to Unicode; -1 means use the current console
136 input codepage. */
139 /* return code -1 means that event_queue_ptr won't be incremented.
140 In other word, this event makes two key codes. (by himi) */
141 static int
142 key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
144 static int mod_key_state = 0;
145 int wParam;
147 *isdead = 0;
149 /* Skip key-up events. */
150 if (!event->bKeyDown)
152 switch (event->wVirtualKeyCode)
154 case VK_LWIN:
155 mod_key_state &= ~LEFT_WIN_PRESSED;
156 break;
157 case VK_RWIN:
158 mod_key_state &= ~RIGHT_WIN_PRESSED;
159 break;
160 case VK_APPS:
161 mod_key_state &= ~APPS_PRESSED;
162 break;
164 return 0;
167 /* Ignore keystrokes we fake ourself; see below. */
168 if (faked_key == event->wVirtualKeyCode)
170 faked_key = 0;
171 return 0;
174 /* To make it easier to debug this code, ignore modifier keys! */
175 switch (event->wVirtualKeyCode)
177 case VK_LWIN:
178 if (NILP (Vw32_pass_lwindow_to_system))
180 /* Prevent system from acting on keyup (which opens the Start
181 menu if no other key was pressed) by simulating a press of
182 Space which we will ignore. */
183 if ((mod_key_state & LEFT_WIN_PRESSED) == 0)
185 if (NUMBERP (Vw32_phantom_key_code))
186 faked_key = XUINT (Vw32_phantom_key_code) & 255;
187 else
188 faked_key = VK_SPACE;
189 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
192 mod_key_state |= LEFT_WIN_PRESSED;
193 if (!NILP (Vw32_lwindow_modifier))
194 return 0;
195 break;
196 case VK_RWIN:
197 if (NILP (Vw32_pass_rwindow_to_system))
199 if ((mod_key_state & RIGHT_WIN_PRESSED) == 0)
201 if (NUMBERP (Vw32_phantom_key_code))
202 faked_key = XUINT (Vw32_phantom_key_code) & 255;
203 else
204 faked_key = VK_SPACE;
205 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
208 mod_key_state |= RIGHT_WIN_PRESSED;
209 if (!NILP (Vw32_rwindow_modifier))
210 return 0;
211 break;
212 case VK_APPS:
213 mod_key_state |= APPS_PRESSED;
214 if (!NILP (Vw32_apps_modifier))
215 return 0;
216 break;
217 case VK_CAPITAL:
218 /* Decide whether to treat as modifier or function key. */
219 if (NILP (Vw32_enable_caps_lock))
220 goto disable_lock_key;
221 return 0;
222 case VK_NUMLOCK:
223 /* Decide whether to treat as modifier or function key. */
224 if (NILP (Vw32_enable_num_lock))
225 goto disable_lock_key;
226 return 0;
227 case VK_SCROLL:
228 /* Decide whether to treat as modifier or function key. */
229 if (NILP (Vw32_scroll_lock_modifier))
230 goto disable_lock_key;
231 return 0;
232 disable_lock_key:
233 /* Ensure the appropriate lock key state is off (and the
234 indicator light as well). */
235 wParam = event->wVirtualKeyCode;
236 if (GetAsyncKeyState (wParam) & 0x8000)
238 /* Fake another press of the relevant key. Apparently, this
239 really is the only way to turn off the indicator. */
240 faked_key = wParam;
241 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
242 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
243 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
244 KEYEVENTF_EXTENDEDKEY | 0, 0);
245 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
246 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
248 break;
249 case VK_MENU:
250 case VK_CONTROL:
251 case VK_SHIFT:
252 return 0;
253 case VK_CANCEL:
254 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
255 which is confusing for purposes of key binding; convert
256 VK_CANCEL events into VK_PAUSE events. */
257 event->wVirtualKeyCode = VK_PAUSE;
258 break;
259 case VK_PAUSE:
260 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
261 for purposes of key binding; convert these back into
262 VK_NUMLOCK events, at least when we want to see NumLock key
263 presses. (Note that there is never any possibility that
264 VK_PAUSE with Ctrl really is C-Pause as per above.) */
265 if (NILP (Vw32_enable_num_lock)
266 && (event->dwControlKeyState
267 & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0)
268 event->wVirtualKeyCode = VK_NUMLOCK;
269 break;
272 /* Recognize state of Windows and Apps keys. */
273 event->dwControlKeyState |= mod_key_state;
275 /* Distinguish numeric keypad keys from extended keys. */
276 event->wVirtualKeyCode =
277 map_keypad_keys (event->wVirtualKeyCode,
278 (event->dwControlKeyState & ENHANCED_KEY));
280 if (lispy_function_keys[event->wVirtualKeyCode] == 0)
282 if (!NILP (Vw32_recognize_altgr)
283 && (event->dwControlKeyState & LEFT_CTRL_PRESSED)
284 && (event->dwControlKeyState & RIGHT_ALT_PRESSED))
286 /* Don't try to interpret AltGr key chords; ToAscii seems not
287 to process them correctly. */
289 /* Handle key chords including any modifiers other than shift
290 directly, in order to preserve as much modifier information as
291 possible. */
292 else if (event->dwControlKeyState
293 & ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED
294 | RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED
295 | (!NILP (Vw32_lwindow_modifier) ? LEFT_WIN_PRESSED : 0)
296 | (!NILP (Vw32_rwindow_modifier) ? RIGHT_WIN_PRESSED : 0)
297 | (!NILP (Vw32_apps_modifier) ? APPS_PRESSED : 0)
298 | (!NILP (Vw32_scroll_lock_modifier) ? SCROLLLOCK_ON : 0)))
300 /* Don't translate modified alphabetic keystrokes, so the user
301 doesn't need to constantly switch layout to type control or
302 meta keystrokes when the normal layout translates
303 alphabetic characters to non-ascii characters. */
304 if ('A' <= event->wVirtualKeyCode && event->wVirtualKeyCode <= 'Z')
306 event->uChar.AsciiChar = event->wVirtualKeyCode;
307 if ((event->dwControlKeyState & SHIFT_PRESSED) == 0)
308 event->uChar.AsciiChar += ('a' - 'A');
310 /* Try to handle unrecognized keystrokes by determining the
311 base character (ie. translating the base key plus shift
312 modifier). */
313 else if (event->uChar.AsciiChar == 0)
314 w32_kbd_patch_key (event, -1);
317 if (event->uChar.AsciiChar == 0)
319 emacs_ev->kind = NO_EVENT;
320 return 0;
322 else if (event->uChar.AsciiChar > 0)
324 /* Pure ASCII characters < 128. */
325 emacs_ev->kind = ASCII_KEYSTROKE_EVENT;
326 emacs_ev->code = event->uChar.AsciiChar;
328 else if (event->uChar.UnicodeChar > 0
329 && w32_console_unicode_input)
331 /* Unicode codepoint; only valid if we are using Unicode
332 console input mode. */
333 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
334 emacs_ev->code = event->uChar.UnicodeChar;
336 else
338 /* Fallback handling of non-ASCII characters for non-Unicode
339 versions of Windows, and for non-Unicode input on NT
340 family of Windows. Only characters in the current
341 console codepage are supported by this fallback. */
342 wchar_t code;
343 char dbcs[2];
344 int cpId;
346 /* Get the current console input codepage to interpret this
347 key with. Note that the system defaults for the OEM
348 codepage could have been changed by calling SetConsoleCP
349 or w32-set-console-codepage, so using GetLocaleInfo to
350 get LOCALE_IDEFAULTCODEPAGE is not TRT here. */
351 cpId = GetConsoleCP ();
353 dbcs[0] = dbcs_lead;
354 dbcs[1] = event->uChar.AsciiChar;
355 if (dbcs_lead)
357 dbcs_lead = 0;
358 if (!MultiByteToWideChar (cpId, 0, dbcs, 2, &code, 1))
360 /* Garbage */
361 DebPrint (("Invalid DBCS sequence: %d %d\n",
362 dbcs[0], dbcs[1]));
363 emacs_ev->kind = NO_EVENT;
366 else if (IsDBCSLeadByteEx (cpId, dbcs[1]))
368 dbcs_lead = dbcs[1];
369 emacs_ev->kind = NO_EVENT;
371 else
373 if (!MultiByteToWideChar (cpId, 0, &dbcs[1], 1, &code, 1))
375 /* Garbage */
376 DebPrint (("Invalid character: %d\n", dbcs[1]));
377 emacs_ev->kind = NO_EVENT;
380 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
381 emacs_ev->code = code;
384 else
386 /* Function keys and other non-character keys. */
387 emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT;
388 emacs_ev->code = event->wVirtualKeyCode;
391 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
392 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState,
393 event->wVirtualKeyCode);
394 emacs_ev->timestamp = GetTickCount ();
395 return 1;
398 /* Mouse position hook. */
399 void
400 w32_console_mouse_position (struct frame **f,
401 int insist,
402 Lisp_Object *bar_window,
403 enum scroll_bar_part *part,
404 Lisp_Object *x,
405 Lisp_Object *y,
406 Time *time)
408 block_input ();
410 insist = insist;
412 *f = get_frame ();
413 *bar_window = Qnil;
414 *part = scroll_bar_above_handle;
415 SELECTED_FRAME ()->mouse_moved = 0;
417 XSETINT (*x, movement_pos.X);
418 XSETINT (*y, movement_pos.Y);
419 *time = movement_time;
421 unblock_input ();
424 /* Remember mouse motion and notify emacs. */
425 static void
426 mouse_moved_to (int x, int y)
428 /* If we're in the same place, ignore it. */
429 if (x != movement_pos.X || y != movement_pos.Y)
431 SELECTED_FRAME ()->mouse_moved = 1;
432 movement_pos.X = x;
433 movement_pos.Y = y;
434 movement_time = GetTickCount ();
438 /* Consoles return button bits in a strange order:
439 least significant - Leftmost button
440 next - Rightmost button
441 next - Leftmost+1
442 next - Leftmost+2...
444 For the 3 standard buttons, we have:
445 Left == 0
446 Middle == 1
447 Right == 2
448 Others increase from there. */
450 #define NUM_TRANSLATED_MOUSE_BUTTONS 5
451 static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] =
453 0, 2, 1, 3, 4
456 static int
457 do_mouse_event (MOUSE_EVENT_RECORD *event,
458 struct input_event *emacs_ev)
460 static DWORD button_state = 0;
461 static Lisp_Object last_mouse_window;
462 DWORD but_change, mask, flags = event->dwEventFlags;
463 int i;
465 switch (flags)
467 case MOUSE_MOVED:
469 struct frame *f = get_frame ();
470 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
471 int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y;
473 mouse_moved_to (mx, my);
475 if (f->mouse_moved)
477 if (hlinfo->mouse_face_hidden)
479 hlinfo->mouse_face_hidden = 0;
480 clear_mouse_face (hlinfo);
483 /* Generate SELECT_WINDOW_EVENTs when needed. */
484 if (!NILP (Vmouse_autoselect_window))
486 Lisp_Object mouse_window = window_from_coordinates (f, mx, my,
487 0, 0);
488 /* A window will be selected only when it is not
489 selected now, and the last mouse movement event was
490 not in it. A minibuffer window will be selected iff
491 it is active. */
492 if (WINDOWP (mouse_window)
493 && !EQ (mouse_window, last_mouse_window)
494 && !EQ (mouse_window, selected_window))
496 struct input_event event;
498 EVENT_INIT (event);
499 event.kind = SELECT_WINDOW_EVENT;
500 event.frame_or_window = mouse_window;
501 event.arg = Qnil;
502 event.timestamp = movement_time;
503 kbd_buffer_store_event (&event);
505 last_mouse_window = mouse_window;
507 else
508 last_mouse_window = Qnil;
510 previous_help_echo_string = help_echo_string;
511 help_echo_string = help_echo_object = help_echo_window = Qnil;
512 help_echo_pos = -1;
513 note_mouse_highlight (f, mx, my);
514 /* If the contents of the global variable help_echo has
515 changed (inside note_mouse_highlight), generate a HELP_EVENT. */
516 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
517 gen_help_event (help_echo_string, selected_frame,
518 help_echo_window, help_echo_object,
519 help_echo_pos);
521 /* We already called kbd_buffer_store_event, so indicate the
522 the caller it shouldn't. */
523 return 0;
525 case MOUSE_WHEELED:
526 case MOUSE_HWHEELED:
528 struct frame *f = get_frame ();
529 int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y;
530 bool down_p = (event->dwButtonState & 0x10000000) != 0;
532 emacs_ev->kind =
533 flags == MOUSE_HWHEELED ? HORIZ_WHEEL_EVENT : WHEEL_EVENT;
534 emacs_ev->code = 0;
535 emacs_ev->modifiers = down_p ? down_modifier : up_modifier;
536 emacs_ev->modifiers |=
537 w32_kbd_mods_to_emacs (event->dwControlKeyState, 0);
538 XSETINT (emacs_ev->x, mx);
539 XSETINT (emacs_ev->y, my);
540 XSETFRAME (emacs_ev->frame_or_window, f);
541 emacs_ev->arg = Qnil;
542 emacs_ev->timestamp = GetTickCount ();
543 return 1;
545 case DOUBLE_CLICK:
546 default: /* mouse pressed or released */
547 /* It looks like the console code sends us a button-release
548 mouse event with dwButtonState == 0 when a window is
549 activated and when the mouse is first clicked. Ignore this
550 case. */
551 if (event->dwButtonState == button_state)
552 return 0;
554 emacs_ev->kind = MOUSE_CLICK_EVENT;
556 /* Find out what button has changed state since the last button
557 event. */
558 but_change = button_state ^ event->dwButtonState;
559 mask = 1;
560 for (i = 0; mask; i++, mask <<= 1)
561 if (but_change & mask)
563 if (i < NUM_TRANSLATED_MOUSE_BUTTONS)
564 emacs_ev->code = emacs_button_translation[i];
565 else
566 emacs_ev->code = i;
567 break;
570 button_state = event->dwButtonState;
571 emacs_ev->modifiers =
572 w32_kbd_mods_to_emacs (event->dwControlKeyState, 0)
573 | ((event->dwButtonState & mask) ? down_modifier : up_modifier);
575 XSETFASTINT (emacs_ev->x, event->dwMousePosition.X);
576 XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y);
577 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
578 emacs_ev->arg = Qnil;
579 emacs_ev->timestamp = GetTickCount ();
581 return 1;
585 static void
586 resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
588 struct frame *f = get_frame ();
590 change_frame_size (f, event->dwSize.X, event->dwSize.Y
591 - FRAME_MENU_BAR_LINES (f), 0, 1, 0, 0);
592 SET_FRAME_GARBAGED (f);
595 static void
596 maybe_generate_resize_event (void)
598 CONSOLE_SCREEN_BUFFER_INFO info;
599 struct frame *f = get_frame ();
601 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
603 /* It is okay to call this unconditionally, since it will do nothing
604 if the size hasn't actually changed. */
605 change_frame_size (f,
606 1 + info.srWindow.Right - info.srWindow.Left,
607 1 + info.srWindow.Bottom - info.srWindow.Top
608 - FRAME_MENU_BAR_LINES (f), 0, 1, 0, 0);
611 #if HAVE_W32NOTIFY
613 handle_file_notifications (struct input_event *hold_quit)
615 BYTE *p = file_notifications;
616 FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p;
617 const DWORD min_size
618 = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t);
619 struct input_event inev;
620 int nevents = 0;
622 /* We cannot process notification before Emacs is fully initialized,
623 since we need the UTF-16LE coding-system to be set up. */
624 if (!initialized)
626 notification_buffer_in_use = 0;
627 return nevents;
630 enter_crit ();
631 if (notification_buffer_in_use)
633 DWORD info_size = notifications_size;
634 Lisp_Object cs = Qutf_16le;
635 Lisp_Object obj = w32_get_watch_object (notifications_desc);
637 /* notifications_size could be zero when the buffer of
638 notifications overflowed on the OS level, or when the
639 directory being watched was itself deleted. Do nothing in
640 that case. */
641 if (info_size
642 && !NILP (obj) && CONSP (obj))
644 Lisp_Object callback = XCDR (obj);
646 EVENT_INIT (inev);
648 while (info_size >= min_size)
650 Lisp_Object utf_16_fn
651 = make_unibyte_string ((char *)fni->FileName,
652 fni->FileNameLength);
653 /* Note: mule-conf is preloaded, so utf-16le must
654 already be defined at this point. */
655 Lisp_Object fname
656 = code_convert_string_norecord (utf_16_fn, cs, 0);
657 Lisp_Object action = lispy_file_action (fni->Action);
659 inev.kind = FILE_NOTIFY_EVENT;
660 inev.timestamp = GetTickCount ();
661 inev.modifiers = 0;
662 inev.frame_or_window = callback;
663 inev.arg = Fcons (action, fname);
664 inev.arg = list3 (make_pointer_integer (notifications_desc),
665 action, fname);
666 kbd_buffer_store_event_hold (&inev, hold_quit);
668 if (!fni->NextEntryOffset)
669 break;
670 p += fni->NextEntryOffset;
671 fni = (PFILE_NOTIFY_INFORMATION)p;
672 info_size -= fni->NextEntryOffset;
675 notification_buffer_in_use = 0;
677 leave_crit ();
678 return nevents;
680 #else /* !HAVE_W32NOTIFY */
682 handle_file_notifications (struct input_event *hold_quit)
684 return 0;
686 #endif /* !HAVE_W32NOTIFY */
688 /* Here's an overview of how Emacs input works in non-GUI sessions on
689 MS-Windows. (For description of the GUI input, see the commentary
690 before w32_msg_pump in w32fns.c.)
692 When Emacs is idle, it loops inside wait_reading_process_output,
693 calling pselect periodically to check whether any input is
694 available. On Windows, pselect is redirected to sys_select, which
695 uses MsgWaitForMultipleObjects to wait for input, either from the
696 keyboard or from any of the Emacs subprocesses. In addition,
697 MsgWaitForMultipleObjects wakes up when some Windows message is
698 posted to the input queue of the Emacs's main thread (which is the
699 thread in which sys_select runs).
701 When the Emacs's console window has focus, Windows sends input
702 events that originate from the keyboard or the mouse; these events
703 wake up MsgWaitForMultipleObjects, which reports that input is
704 available. Emacs then calls w32_console_read_socket, below, to
705 read the input. w32_console_read_socket uses
706 GetNumberOfConsoleInputEvents and ReadConsoleInput to peek at and
707 read the console input events.
709 One type of non-keyboard input event that gets reported as input
710 available is due to the Emacs's console window receiving focus.
711 When that happens, Emacs gets the FOCUS_EVENT event and sys_select
712 reports some input; however, w32_console_read_socket ignores such
713 events when called to read them.
715 Note that any other Windows message sent to the main thread will
716 also wake up MsgWaitForMultipleObjects. These messages get
717 immediately dispatched to their destinations by calling
718 drain_message_queue. */
721 w32_console_read_socket (struct terminal *terminal,
722 struct input_event *hold_quit)
724 int nev, add;
725 int isdead;
727 block_input ();
729 for (;;)
731 int nfnotify = handle_file_notifications (hold_quit);
733 nev = fill_queue (0);
734 if (nev <= 0)
736 /* If nev == -1, there was some kind of error
737 If nev == 0 then no events were available
738 so return. */
739 if (nfnotify)
740 nev = 0;
741 break;
744 while (nev > 0)
746 struct input_event inev;
747 /* Having a separate variable with this value makes
748 debugging easier, as otherwise the compiler might
749 rearrange the switch below in a way that makes it hard to
750 track the event type. */
751 unsigned evtype = queue_ptr->EventType;
753 EVENT_INIT (inev);
754 inev.kind = NO_EVENT;
755 inev.arg = Qnil;
757 switch (evtype)
759 case KEY_EVENT:
760 add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead);
761 if (add == -1) /* 95.7.25 by himi */
763 queue_ptr--;
764 add = 1;
766 if (add)
767 kbd_buffer_store_event_hold (&inev, hold_quit);
768 break;
770 case MOUSE_EVENT:
771 add = do_mouse_event (&queue_ptr->Event.MouseEvent, &inev);
772 if (add)
773 kbd_buffer_store_event_hold (&inev, hold_quit);
774 break;
776 case WINDOW_BUFFER_SIZE_EVENT:
777 if (w32_use_full_screen_buffer)
778 resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
779 break;
781 case MENU_EVENT:
782 case FOCUS_EVENT:
783 /* Internal event types, ignored. */
784 break;
787 queue_ptr++;
788 nev--;
792 /* We don't get told about changes in the window size (only the buffer
793 size, which we no longer care about), so we have to check it
794 periodically. */
795 if (!w32_use_full_screen_buffer)
796 maybe_generate_resize_event ();
798 unblock_input ();
799 return nev;