dired-x.el misc cleanup.
[emacs.git] / src / w32inevt.c
blobd0b097100fd2e4d28bcf32b12862835a65ef2761
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/>. */
20 Drew Bliss 01-Oct-93
21 Adapted from ntkbd.c by Tim Fleehart
25 #include <config.h>
26 #include <stdio.h>
27 #include <windows.h>
28 #include <setjmp.h>
30 #ifndef MOUSE_MOVED
31 #define MOUSE_MOVED 1
32 #endif
34 #include "lisp.h"
35 #include "keyboard.h"
36 #include "frame.h"
37 #include "dispextern.h"
38 #include "blockinput.h"
39 #include "termhooks.h"
40 #include "w32heap.h"
41 #include "w32term.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;
50 /* from keyboard.c */
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);
57 /* Event queue */
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;
65 static int
66 fill_queue (BOOL block)
68 BOOL rc;
69 DWORD events_waiting;
71 if (queue_ptr < queue_end)
72 return queue_end-queue_ptr;
74 if (!block)
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))
79 return -1;
80 if (events_waiting == 0)
81 return 0;
84 rc = ReadConsoleInput (keyboard_handle, event_queue, EVENT_QUEUE_SIZE,
85 &events_waiting);
86 if (!rc)
87 return -1;
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. */
97 static FRAME_PTR
98 get_frame (void)
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)
108 int retval = 0;
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)
142 || (key == VK_TAB)
143 || (key == VK_CLEAR)
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;
155 else
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;
164 return retval;
167 #if 0
168 /* Return nonzero if the virtual key is a dead key. */
169 static int
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;
177 #endif
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;
185 BYTE keystate[256];
186 static BYTE ansi_code[4];
187 static int isdead = 0;
189 if (isdead == 2)
191 event->uChar.AsciiChar = ansi_code[2];
192 isdead = 0;
193 return 1;
195 if (event->uChar.AsciiChar != 0)
196 return 1;
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;
215 #if 0
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))
224 return 0;
225 #endif
227 /* On NT, call ToUnicode instead and then convert to the current
228 locale's default codepage. */
229 if (os_subtype == OS_NT)
231 WCHAR buf[128];
233 isdead = ToUnicode (event->wVirtualKeyCode, event->wVirtualScanCode,
234 keystate, buf, 128, 0);
235 if (isdead > 0)
237 char cp[20];
238 int cpId;
240 event->uChar.UnicodeChar = buf[isdead - 1];
242 GetLocaleInfo (GetThreadLocale (),
243 LOCALE_IDEFAULTANSICODEPAGE, cp, 20);
244 cpId = atoi (cp);
245 isdead = WideCharToMultiByte (cpId, 0, buf, isdead,
246 ansi_code, 4, NULL, NULL);
248 else
249 isdead = 0;
251 else
253 isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode,
254 keystate, (LPWORD) ansi_code, 0);
257 if (isdead == 0)
258 return 0;
259 event->uChar.AsciiChar = ansi_code[0];
260 return isdead;
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) */
270 static int
271 key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
273 static int mod_key_state = 0;
274 int wParam;
276 *isdead = 0;
278 /* Skip key-up events. */
279 if (!event->bKeyDown)
281 switch (event->wVirtualKeyCode)
283 case VK_LWIN:
284 mod_key_state &= ~LEFT_WIN_PRESSED;
285 break;
286 case VK_RWIN:
287 mod_key_state &= ~RIGHT_WIN_PRESSED;
288 break;
289 case VK_APPS:
290 mod_key_state &= ~APPS_PRESSED;
291 break;
293 return 0;
296 /* Ignore keystrokes we fake ourself; see below. */
297 if (faked_key == event->wVirtualKeyCode)
299 faked_key = 0;
300 return 0;
303 /* To make it easier to debug this code, ignore modifier keys! */
304 switch (event->wVirtualKeyCode)
306 case VK_LWIN:
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;
316 else
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))
323 return 0;
324 break;
325 case VK_RWIN:
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;
332 else
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))
339 return 0;
340 break;
341 case VK_APPS:
342 mod_key_state |= APPS_PRESSED;
343 if (!NILP (Vw32_apps_modifier))
344 return 0;
345 break;
346 case VK_CAPITAL:
347 /* Decide whether to treat as modifier or function key. */
348 if (NILP (Vw32_enable_caps_lock))
349 goto disable_lock_key;
350 return 0;
351 case VK_NUMLOCK:
352 /* Decide whether to treat as modifier or function key. */
353 if (NILP (Vw32_enable_num_lock))
354 goto disable_lock_key;
355 return 0;
356 case VK_SCROLL:
357 /* Decide whether to treat as modifier or function key. */
358 if (NILP (Vw32_scroll_lock_modifier))
359 goto disable_lock_key;
360 return 0;
361 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. */
369 faked_key = wParam;
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);
377 break;
378 case VK_MENU:
379 case VK_CONTROL:
380 case VK_SHIFT:
381 return 0;
382 case VK_CANCEL:
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;
387 break;
388 case 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;
398 break;
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
420 possible. */
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
441 modifier). */
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;
449 return 0;
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;
461 else
463 /* Fallback for non-Unicode versions of Windows. */
464 wchar_t code;
465 char dbcs[2];
466 char cp[20];
467 int cpId;
469 /* Get the codepage to interpret this key with. */
470 GetLocaleInfo (GetThreadLocale (),
471 LOCALE_IDEFAULTANSICODEPAGE, cp, 20);
472 cpId = atoi (cp);
474 dbcs[0] = dbcs_lead;
475 dbcs[1] = event->uChar.AsciiChar;
476 if (dbcs_lead)
478 dbcs_lead = 0;
479 if (!MultiByteToWideChar (cpId, 0, dbcs, 2, &code, 1))
481 /* Garbage */
482 DebPrint (("Invalid DBCS sequence: %d %d\n",
483 dbcs[0], dbcs[1]));
484 emacs_ev->kind = NO_EVENT;
487 else if (IsDBCSLeadByteEx (cpId, dbcs[1]))
489 dbcs_lead = dbcs[1];
490 emacs_ev->kind = NO_EVENT;
492 else
494 if (!MultiByteToWideChar (cpId, 0, &dbcs[1], 1, &code, 1))
496 /* Garbage */
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;
505 else
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 ();
515 return 1;
519 w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state)
521 int cur_state = (GetKeyState (vk_code) & 1);
523 if (NILP (new_state)
524 || (NUMBERP (new_state)
525 && ((XUINT (new_state)) & 1) != cur_state))
527 faked_key = vk_code;
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;
541 return cur_state;
544 /* Mouse position hook. */
545 void
546 w32_console_mouse_position (FRAME_PTR *f,
547 int insist,
548 Lisp_Object *bar_window,
549 enum scroll_bar_part *part,
550 Lisp_Object *x,
551 Lisp_Object *y,
552 unsigned long *time)
554 BLOCK_INPUT;
556 insist = insist;
558 *f = get_frame ();
559 *bar_window = Qnil;
560 *part = 0;
561 SELECTED_FRAME ()->mouse_moved = 0;
563 XSETINT (*x, movement_pos.X);
564 XSETINT (*y, movement_pos.Y);
565 *time = movement_time;
567 UNBLOCK_INPUT;
570 /* Remember mouse motion and notify emacs. */
571 static void
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;
578 movement_pos.X = x;
579 movement_pos.Y = y;
580 movement_time = GetTickCount ();
584 /* Consoles return button bits in a strange order:
585 least significant - Leftmost button
586 next - Rightmost button
587 next - Leftmost+1
588 next - Leftmost+2...
590 Assume emacs likes three button mice, so
591 Left == 0
592 Middle == 1
593 Right == 2
594 Others increase from there. */
596 #define NUM_TRANSLATED_MOUSE_BUTTONS 3
597 static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] =
599 0, 2, 1
602 static int
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;
608 int i;
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);
615 return 0;
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)
621 return 0;
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;
627 mask = 1;
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];
633 else
634 emacs_ev->code = i;
635 break;
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 */
646 #ifdef MULE
647 XSET (emacs_ev->frame_or_window, Lisp_Frame, get_frame ());
648 #else
649 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
650 #endif
652 return 1;
655 static void
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);
664 static void
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,
677 0, 0, 0);
681 w32_console_read_socket (struct terminal *terminal,
682 int expected,
683 struct input_event *hold_quit)
685 BOOL no_events = TRUE;
686 int nev, ret = 0, add;
687 int isdead;
689 if (interrupt_input_blocked)
691 interrupt_input_pending = 1;
692 return -1;
695 interrupt_input_pending = 0;
696 BLOCK_INPUT;
698 for (;;)
700 nev = fill_queue (0);
701 if (nev <= 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
705 so return. */
706 UNBLOCK_INPUT;
707 return nev;
710 while (nev > 0)
712 struct input_event inev;
714 EVENT_INIT (inev);
715 inev.kind = NO_EVENT;
716 inev.arg = Qnil;
718 switch (queue_ptr->EventType)
720 case KEY_EVENT:
721 add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead);
722 if (add == -1) /* 95.7.25 by himi */
724 queue_ptr--;
725 add = 1;
727 if (add)
728 kbd_buffer_store_event_hold (&inev, hold_quit);
729 break;
731 case MOUSE_EVENT:
732 add = do_mouse_event (&queue_ptr->Event.MouseEvent, &inev);
733 if (add)
734 kbd_buffer_store_event_hold (&inev, hold_quit);
735 break;
737 case WINDOW_BUFFER_SIZE_EVENT:
738 if (w32_use_full_screen_buffer)
739 resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
740 break;
742 case MENU_EVENT:
743 case FOCUS_EVENT:
744 /* Internal event types, ignored. */
745 break;
748 queue_ptr++;
749 nev--;
752 if (ret > 0 || expected == 0)
753 break;
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
758 periodically. */
759 if (!w32_use_full_screen_buffer)
760 maybe_generate_resize_event ();
762 UNBLOCK_INPUT;
763 return ret;