replace XTYPE calls in nextstep files
[bpt/emacs.git] / src / w32inevt.c
CommitLineData
b46a6a83 1/* Input event support for Emacs on the Microsoft Windows API.
ba318903 2 Copyright (C) 1992-1993, 1995, 2001-2014 Free Software Foundation,
ab422c4d 3 Inc.
6cdfb6e6 4
3b7ad313
EN
5This file is part of GNU Emacs.
6
9ec0b715 7GNU Emacs is free software: you can redistribute it and/or modify
3b7ad313 8it under the terms of the GNU General Public License as published by
9ec0b715
GM
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
3b7ad313
EN
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
9ec0b715 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
6cdfb6e6 19
9ec0b715 20/*
6cdfb6e6
RS
21 Drew Bliss 01-Oct-93
22 Adapted from ntkbd.c by Tim Fleehart
23*/
24
25
4838e624 26#include <config.h>
6cdfb6e6
RS
27#include <stdio.h>
28#include <windows.h>
29
690e96a3
AI
30#ifndef MOUSE_MOVED
31#define MOUSE_MOVED 1
32#endif
5d64d770
EZ
33#ifndef MOUSE_HWHEELED
34#define MOUSE_HWHEELED 8
35#endif
690e96a3 36
6cdfb6e6 37#include "lisp.h"
690e96a3 38#include "keyboard.h"
6cdfb6e6 39#include "frame.h"
2165e881 40#include "dispextern.h"
f12fdf02 41#include "window.h"
6cdfb6e6
RS
42#include "blockinput.h"
43#include "termhooks.h"
42e3a361 44#include "termchar.h"
29a2c30f
GV
45#include "w32heap.h"
46#include "w32term.h"
01bd1b0d 47#include "w32inevt.h"
6cdfb6e6 48
7684e57b 49/* stdin, from w32console.c */
6cdfb6e6
RS
50extern HANDLE keyboard_handle;
51
6cdfb6e6
RS
52/* Info for last mouse motion */
53static COORD movement_pos;
9fbd6841 54static Time movement_time;
6cdfb6e6 55
7684e57b 56/* from w32fns.c */
29a2c30f 57extern unsigned int map_keypad_keys (unsigned int, unsigned int);
29a2c30f 58extern unsigned int w32_key_to_modifier (int key);
59131421 59
6cdfb6e6
RS
60/* Event queue */
61#define EVENT_QUEUE_SIZE 50
62static INPUT_RECORD event_queue[EVENT_QUEUE_SIZE];
63static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue;
64
7e233730
JR
65/* Temporarily store lead byte of DBCS input sequences. */
66static char dbcs_lead = 0;
67
01bd1b0d
EZ
68static inline BOOL
69w32_read_console_input (HANDLE h, INPUT_RECORD *rec, DWORD recsize,
70 DWORD *waiting)
71{
72 return (w32_console_unicode_input
73 ? ReadConsoleInputW (h, rec, recsize, waiting)
74 : ReadConsoleInputA (h, rec, recsize, waiting));
75}
76
0fda9b75
DC
77/* Set by w32_console_toggle_lock_key. */
78int faked_key;
79
177c0ea7 80static int
6cdfb6e6
RS
81fill_queue (BOOL block)
82{
83 BOOL rc;
84 DWORD events_waiting;
177c0ea7 85
6cdfb6e6
RS
86 if (queue_ptr < queue_end)
87 return queue_end-queue_ptr;
177c0ea7 88
6cdfb6e6
RS
89 if (!block)
90 {
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;
97 }
177c0ea7 98
01bd1b0d
EZ
99 rc = w32_read_console_input (keyboard_handle, event_queue, EVENT_QUEUE_SIZE,
100 &events_waiting);
6cdfb6e6
RS
101 if (!rc)
102 return -1;
103 queue_ptr = event_queue;
104 queue_end = event_queue + events_waiting;
105 return (int) events_waiting;
106}
107
108/* In a generic, multi-frame world this should take a console handle
a10c8269 109 and return the frame for it.
6cdfb6e6
RS
110
111 Right now, there's only one frame so return it. */
a10c8269 112static struct frame *
6cdfb6e6
RS
113get_frame (void)
114{
4f4a5f69 115 return SELECTED_FRAME ();
6cdfb6e6
RS
116}
117
177c0ea7 118/* Translate console modifiers to emacs modifiers.
b02466e8 119 German keyboard support (Kai Morgan Zeise 2/18/95). */
b02466e8 120
b02466e8 121
29a2c30f
GV
122#if 0
123/* Return nonzero if the virtual key is a dead key. */
124static int
125is_dead_key (int wparam)
126{
127 unsigned int code = MapVirtualKey (wparam, 2);
128
129 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
130 return (code & 0x80008000) ? 1 : 0;
131}
132#endif
133
302fc036
EZ
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. */
407c1745 137
6cdfb6e6 138
177c0ea7 139/* return code -1 means that event_queue_ptr won't be incremented.
daf38066 140 In other word, this event makes two key codes. (by himi) */
24f981c9 141static int
59131421 142key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
6cdfb6e6 143{
29a2c30f
GV
144 static int mod_key_state = 0;
145 int wParam;
59131421
GV
146
147 *isdead = 0;
29a2c30f 148
6cdfb6e6 149 /* Skip key-up events. */
407c1745 150 if (!event->bKeyDown)
6cdfb6e6 151 {
29a2c30f
GV
152 switch (event->wVirtualKeyCode)
153 {
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;
163 }
6cdfb6e6
RS
164 return 0;
165 }
b02466e8 166
29a2c30f
GV
167 /* Ignore keystrokes we fake ourself; see below. */
168 if (faked_key == event->wVirtualKeyCode)
6cdfb6e6 169 {
29a2c30f 170 faked_key = 0;
6cdfb6e6
RS
171 return 0;
172 }
29a2c30f
GV
173
174 /* To make it easier to debug this code, ignore modifier keys! */
175 switch (event->wVirtualKeyCode)
6cdfb6e6 176 {
29a2c30f
GV
177 case VK_LWIN:
178 if (NILP (Vw32_pass_lwindow_to_system))
179 {
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)
184 {
9ddef9c4
GV
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);
29a2c30f
GV
190 }
191 }
192 mod_key_state |= LEFT_WIN_PRESSED;
193 if (!NILP (Vw32_lwindow_modifier))
daf38066 194 return 0;
29a2c30f
GV
195 break;
196 case VK_RWIN:
197 if (NILP (Vw32_pass_rwindow_to_system))
198 {
199 if ((mod_key_state & RIGHT_WIN_PRESSED) == 0)
200 {
9ddef9c4
GV
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);
29a2c30f
GV
206 }
207 }
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)
237 {
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);
247 }
248 break;
249 case VK_MENU:
250 case VK_CONTROL:
251 case VK_SHIFT:
252 return 0;
9ddef9c4
GV
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;
6cdfb6e6 270 }
29a2c30f
GV
271
272 /* Recognize state of Windows and Apps keys. */
273 event->dwControlKeyState |= mod_key_state;
274
275 /* Distinguish numeric keypad keys from extended keys. */
276 event->wVirtualKeyCode =
277 map_keypad_keys (event->wVirtualKeyCode,
278 (event->dwControlKeyState & ENHANCED_KEY));
279
280 if (lispy_function_keys[event->wVirtualKeyCode] == 0)
daf38066 281 {
29a2c30f
GV
282 if (!NILP (Vw32_recognize_altgr)
283 && (event->dwControlKeyState & LEFT_CTRL_PRESSED)
284 && (event->dwControlKeyState & RIGHT_ALT_PRESSED))
daf38066 285 {
29a2c30f
GV
286 /* Don't try to interpret AltGr key chords; ToAscii seems not
287 to process them correctly. */
daf38066 288 }
29a2c30f
GV
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)))
299 {
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')
305 {
306 event->uChar.AsciiChar = event->wVirtualKeyCode;
307 if ((event->dwControlKeyState & SHIFT_PRESSED) == 0)
308 event->uChar.AsciiChar += ('a' - 'A');
309 }
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)
302fc036 314 w32_kbd_patch_key (event, -1);
29a2c30f 315 }
7e233730 316
29a2c30f 317 if (event->uChar.AsciiChar == 0)
7e233730
JR
318 {
319 emacs_ev->kind = NO_EVENT;
320 return 0;
321 }
af93af83 322 else if (event->uChar.AsciiChar > 0)
7e233730 323 {
01bd1b0d 324 /* Pure ASCII characters < 128. */
7e233730
JR
325 emacs_ev->kind = ASCII_KEYSTROKE_EVENT;
326 emacs_ev->code = event->uChar.AsciiChar;
327 }
01bd1b0d
EZ
328 else if (event->uChar.UnicodeChar > 0
329 && w32_console_unicode_input)
7e233730 330 {
01bd1b0d
EZ
331 /* Unicode codepoint; only valid if we are using Unicode
332 console input mode. */
7e233730
JR
333 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
334 emacs_ev->code = event->uChar.UnicodeChar;
335 }
336 else
337 {
01bd1b0d
EZ
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. */
7e233730
JR
342 wchar_t code;
343 char dbcs[2];
7e233730
JR
344 int cpId;
345
01bd1b0d
EZ
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 ();
7e233730
JR
352
353 dbcs[0] = dbcs_lead;
354 dbcs[1] = event->uChar.AsciiChar;
355 if (dbcs_lead)
356 {
357 dbcs_lead = 0;
358 if (!MultiByteToWideChar (cpId, 0, dbcs, 2, &code, 1))
359 {
360 /* Garbage */
361 DebPrint (("Invalid DBCS sequence: %d %d\n",
362 dbcs[0], dbcs[1]));
dd5de7c6 363 emacs_ev->kind = NO_EVENT;
7e233730
JR
364 }
365 }
366 else if (IsDBCSLeadByteEx (cpId, dbcs[1]))
367 {
368 dbcs_lead = dbcs[1];
dd5de7c6 369 emacs_ev->kind = NO_EVENT;
7e233730
JR
370 }
371 else
372 {
373 if (!MultiByteToWideChar (cpId, 0, &dbcs[1], 1, &code, 1))
374 {
375 /* Garbage */
376 DebPrint (("Invalid character: %d\n", dbcs[1]));
dd5de7c6 377 emacs_ev->kind = NO_EVENT;
7e233730
JR
378 }
379 }
380 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
381 emacs_ev->code = code;
382 }
daf38066 383 }
6cdfb6e6
RS
384 else
385 {
01bd1b0d 386 /* Function keys and other non-character keys. */
e43bd4f5 387 emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT;
e3ec1dce 388 emacs_ev->code = event->wVirtualKeyCode;
6cdfb6e6 389 }
29a2c30f 390
b02466e8 391 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
59131421
GV
392 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState,
393 event->wVirtualKeyCode);
6cdfb6e6
RS
394 emacs_ev->timestamp = GetTickCount ();
395 return 1;
396}
397
398/* Mouse position hook. */
177c0ea7 399void
a10c8269 400w32_console_mouse_position (struct frame **f,
81e3e4fd 401 int insist,
81e3e4fd
GV
402 Lisp_Object *bar_window,
403 enum scroll_bar_part *part,
404 Lisp_Object *x,
405 Lisp_Object *y,
9fbd6841 406 Time *time)
6cdfb6e6 407{
4d7e6e51 408 block_input ();
407c1745 409
b02466e8
KH
410 insist = insist;
411
6cdfb6e6
RS
412 *f = get_frame ();
413 *bar_window = Qnil;
414 *part = 0;
4f4a5f69 415 SELECTED_FRAME ()->mouse_moved = 0;
177c0ea7 416
ed3751c8
JB
417 XSETINT (*x, movement_pos.X);
418 XSETINT (*y, movement_pos.Y);
6cdfb6e6 419 *time = movement_time;
177c0ea7 420
4d7e6e51 421 unblock_input ();
6cdfb6e6
RS
422}
423
42e3a361 424/* Remember mouse motion and notify emacs. */
177c0ea7 425static void
6cdfb6e6
RS
426mouse_moved_to (int x, int y)
427{
eb3f6f01 428 /* If we're in the same place, ignore it. */
6cdfb6e6
RS
429 if (x != movement_pos.X || y != movement_pos.Y)
430 {
42e3a361 431 SELECTED_FRAME ()->mouse_moved = 1;
6cdfb6e6
RS
432 movement_pos.X = x;
433 movement_pos.Y = y;
434 movement_time = GetTickCount ();
435 }
436}
437
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...
443
5d64d770 444 For the 3 standard buttons, we have:
6cdfb6e6
RS
445 Left == 0
446 Middle == 1
447 Right == 2
448 Others increase from there. */
449
5d64d770 450#define NUM_TRANSLATED_MOUSE_BUTTONS 5
1f2fca4b 451static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] =
6cdfb6e6 452{
5d64d770 453 0, 2, 1, 3, 4
6cdfb6e6
RS
454};
455
177c0ea7 456static int
6cdfb6e6
RS
457do_mouse_event (MOUSE_EVENT_RECORD *event,
458 struct input_event *emacs_ev)
459{
460 static DWORD button_state = 0;
f12fdf02 461 static Lisp_Object last_mouse_window;
5d64d770 462 DWORD but_change, mask, flags = event->dwEventFlags;
6cdfb6e6 463 int i;
177c0ea7 464
5d64d770 465 switch (flags)
6cdfb6e6 466 {
5d64d770 467 case MOUSE_MOVED:
6cdfb6e6 468 {
5d64d770
EZ
469 struct frame *f = get_frame ();
470 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
471 int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y;
472
473 mouse_moved_to (mx, my);
474
475 if (f->mouse_moved)
476 {
477 if (hlinfo->mouse_face_hidden)
478 {
479 hlinfo->mouse_face_hidden = 0;
480 clear_mouse_face (hlinfo);
481 }
482
483 /* Generate SELECT_WINDOW_EVENTs when needed. */
484 if (!NILP (Vmouse_autoselect_window))
485 {
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))
495 {
496 struct input_event event;
497
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);
504 }
505 last_mouse_window = mouse_window;
506 }
507 else
508 last_mouse_window = Qnil;
509
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);
520 }
a67c4ae0 521 /* We already called kbd_buffer_store_event, so indicate the
5d64d770
EZ
522 the caller it shouldn't. */
523 return 0;
6cdfb6e6 524 }
5d64d770
EZ
525 case MOUSE_WHEELED:
526 case MOUSE_HWHEELED:
527 {
528 struct frame *f = get_frame ();
529 int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y;
530 bool down_p = (event->dwButtonState & 0x10000000) != 0;
531
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;
544 }
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;
6cdfb6e6 553
5d64d770
EZ
554 emacs_ev->kind = MOUSE_CLICK_EVENT;
555
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)
562 {
563 if (i < NUM_TRANSLATED_MOUSE_BUTTONS)
564 emacs_ev->code = emacs_button_translation[i];
565 else
566 emacs_ev->code = i;
567 break;
568 }
569
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);
574
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 ();
580
581 return 1;
582 }
6cdfb6e6
RS
583}
584
177c0ea7 585static void
6cdfb6e6
RS
586resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
587{
a10c8269 588 struct frame *f = get_frame ();
177c0ea7 589
880e6158 590 change_frame_size (f, event->dwSize.X, event->dwSize.Y, 0, 1, 0, 0);
6cdfb6e6
RS
591 SET_FRAME_GARBAGED (f);
592}
593
b7b97897 594static void
b56ceb92 595maybe_generate_resize_event (void)
b7b97897
AI
596{
597 CONSOLE_SCREEN_BUFFER_INFO info;
a10c8269 598 struct frame *f = get_frame ();
b7b97897
AI
599
600 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
601
602 /* It is okay to call this unconditionally, since it will do nothing
603 if the size hasn't actually changed. */
604 change_frame_size (f,
b7b97897 605 1 + info.srWindow.Right - info.srWindow.Left,
880e6158
MR
606 1 + info.srWindow.Bottom - info.srWindow.Top,
607 0, 0, 0, 0);
b7b97897
AI
608}
609
7f203aa1 610#if HAVE_W32NOTIFY
9c099ca7 611int
182b170f
EZ
612handle_file_notifications (struct input_event *hold_quit)
613{
614 BYTE *p = file_notifications;
615 FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p;
616 const DWORD min_size
617 = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t);
618 struct input_event inev;
4f0800ec 619 int nevents = 0;
182b170f
EZ
620
621 /* We cannot process notification before Emacs is fully initialized,
622 since we need the UTF-16LE coding-system to be set up. */
623 if (!initialized)
624 {
625 notification_buffer_in_use = 0;
4f0800ec 626 return nevents;
182b170f
EZ
627 }
628
629 enter_crit ();
630 if (notification_buffer_in_use)
631 {
632 DWORD info_size = notifications_size;
4f0800ec 633 Lisp_Object cs = intern ("utf-16le");
0b86d359 634 Lisp_Object obj = w32_get_watch_object (notifications_desc);
182b170f
EZ
635
636 /* notifications_size could be zero when the buffer of
637 notifications overflowed on the OS level, or when the
638 directory being watched was itself deleted. Do nothing in
639 that case. */
4f0800ec
EZ
640 if (info_size
641 && !NILP (obj) && CONSP (obj))
182b170f 642 {
4f0800ec
EZ
643 Lisp_Object callback = XCDR (obj);
644
182b170f
EZ
645 EVENT_INIT (inev);
646
647 while (info_size >= min_size)
648 {
649 Lisp_Object utf_16_fn
650 = make_unibyte_string ((char *)fni->FileName,
651 fni->FileNameLength);
652 /* Note: mule-conf is preloaded, so utf-16le must
653 already be defined at this point. */
654 Lisp_Object fname
4f0800ec 655 = code_convert_string_norecord (utf_16_fn, cs, 0);
182b170f 656 Lisp_Object action = lispy_file_action (fni->Action);
182b170f 657
4f0800ec 658 inev.kind = FILE_NOTIFY_EVENT;
d884121b 659 inev.code = (ptrdiff_t)XINT (XIL ((EMACS_INT)notifications_desc));
4f0800ec
EZ
660 inev.timestamp = GetTickCount ();
661 inev.modifiers = 0;
662 inev.frame_or_window = callback;
663 inev.arg = Fcons (action, fname);
664 kbd_buffer_store_event_hold (&inev, hold_quit);
182b170f
EZ
665
666 if (!fni->NextEntryOffset)
667 break;
668 p += fni->NextEntryOffset;
669 fni = (PFILE_NOTIFY_INFORMATION)p;
670 info_size -= fni->NextEntryOffset;
671 }
672 }
673 notification_buffer_in_use = 0;
674 }
675 leave_crit ();
4f0800ec 676 return nevents;
182b170f 677}
7f203aa1 678#else /* !HAVE_W32NOTIFY */
9c099ca7 679int
7f203aa1
EZ
680handle_file_notifications (struct input_event *hold_quit)
681{
682 return 0;
683}
684#endif /* !HAVE_W32NOTIFY */
182b170f 685
605a3df6
EZ
686/* Here's an overview of how Emacs input works in non-GUI sessions on
687 MS-Windows. (For description of the GUI input, see the commentary
688 before w32_msg_pump in w32fns.c.)
689
690 When Emacs is idle, it loops inside wait_reading_process_output,
691 calling pselect periodically to check whether any input is
692 available. On Windows, pselect is redirected to sys_select, which
693 uses MsgWaitForMultipleObjects to wait for input, either from the
694 keyboard or from any of the Emacs subprocesses. In addition,
695 MsgWaitForMultipleObjects wakes up when some Windows message is
696 posted to the input queue of the Emacs's main thread (which is the
697 thread in which sys_select runs).
698
699 When the Emacs's console window has focus, Windows sends input
700 events that originate from the keyboard or the mouse; these events
701 wake up MsgWaitForMultipleObjects, which reports that input is
702 available. Emacs then calls w32_console_read_socket, below, to
703 read the input. w32_console_read_socket uses
704 GetNumberOfConsoleInputEvents and ReadConsoleInput to peek at and
705 read the console input events.
706
707 One type of non-keyboard input event that gets reported as input
708 available is due to the Emacs's console window receiving focus.
709 When that happens, Emacs gets the FOCUS_EVENT event and sys_select
710 reports some input; however, w32_console_read_socket ignores such
711 events when called to read them.
712
713 Note that any other Windows message sent to the main thread will
714 also wake up MsgWaitForMultipleObjects. These messages get
715 immediately dispatched to their destinations by calling
716 drain_message_queue. */
717
177c0ea7 718int
9e511e9c 719w32_console_read_socket (struct terminal *terminal,
9e511e9c 720 struct input_event *hold_quit)
6cdfb6e6 721{
e4bce92a 722 int nev, add;
59131421
GV
723 int isdead;
724
4d7e6e51 725 block_input ();
177c0ea7 726
6cdfb6e6
RS
727 for (;;)
728 {
4f0800ec
EZ
729 int nfnotify = handle_file_notifications (hold_quit);
730
06c2c73d 731 nev = fill_queue (0);
6cdfb6e6
RS
732 if (nev <= 0)
733 {
734 /* If nev == -1, there was some kind of error
4f0800ec 735 If nev == 0 then no events were available
6cdfb6e6 736 so return. */
4f0800ec
EZ
737 if (nfnotify)
738 nev = 0;
e4bce92a 739 break;
6cdfb6e6
RS
740 }
741
9cd31aaf 742 while (nev > 0)
6cdfb6e6 743 {
9cd31aaf 744 struct input_event inev;
f0177f86
EZ
745 /* Having a separate variable with this value makes
746 debugging easier, as otherwise the compiler might
747 rearrange the switch below in a way that makes it hard to
748 track the event type. */
749 unsigned evtype = queue_ptr->EventType;
9cd31aaf
KS
750
751 EVENT_INIT (inev);
752 inev.kind = NO_EVENT;
753 inev.arg = Qnil;
754
f0177f86 755 switch (evtype)
6cdfb6e6
RS
756 {
757 case KEY_EVENT:
9cd31aaf 758 add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead);
daf38066 759 if (add == -1) /* 95.7.25 by himi */
177c0ea7 760 {
daf38066
GV
761 queue_ptr--;
762 add = 1;
763 }
9cd31aaf
KS
764 if (add)
765 kbd_buffer_store_event_hold (&inev, hold_quit);
6cdfb6e6
RS
766 break;
767
768 case MOUSE_EVENT:
9cd31aaf
KS
769 add = do_mouse_event (&queue_ptr->Event.MouseEvent, &inev);
770 if (add)
771 kbd_buffer_store_event_hold (&inev, hold_quit);
6cdfb6e6
RS
772 break;
773
774 case WINDOW_BUFFER_SIZE_EVENT:
d44c074d
AI
775 if (w32_use_full_screen_buffer)
776 resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
6cdfb6e6 777 break;
177c0ea7 778
6cdfb6e6
RS
779 case MENU_EVENT:
780 case FOCUS_EVENT:
781 /* Internal event types, ignored. */
782 break;
783 }
177c0ea7 784
6cdfb6e6
RS
785 queue_ptr++;
786 nev--;
787 }
6cdfb6e6 788 }
b7b97897
AI
789
790 /* We don't get told about changes in the window size (only the buffer
791 size, which we no longer care about), so we have to check it
792 periodically. */
d44c074d
AI
793 if (!w32_use_full_screen_buffer)
794 maybe_generate_resize_event ();
b7b97897 795
4d7e6e51 796 unblock_input ();
e4bce92a 797 return nev;
6cdfb6e6 798}