Merge from emacs-24; up to 2012-05-02T07:12:52Z!rgm@gnu.org.
[bpt/emacs.git] / src / w32inevt.c
1 /* Input event support for Emacs on the Microsoft Windows API.
2 Copyright (C) 1992-1993, 1995, 2001-2012 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
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.
10
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.
15
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/>. */
18
19 /*
20 Drew Bliss 01-Oct-93
21 Adapted from ntkbd.c by Tim Fleehart
22 */
23
24
25 #include <config.h>
26 #include <stdio.h>
27 #include <windows.h>
28 #include <setjmp.h>
29
30 #ifndef MOUSE_MOVED
31 #define MOUSE_MOVED 1
32 #endif
33
34 #include "lisp.h"
35 #include "keyboard.h"
36 #include "frame.h"
37 #include "dispextern.h"
38 #include "window.h"
39 #include "blockinput.h"
40 #include "termhooks.h"
41 #include "termchar.h"
42 #include "w32heap.h"
43 #include "w32term.h"
44 #include "w32inevt.h"
45
46 /* stdin, from w32console.c */
47 extern HANDLE keyboard_handle;
48
49 /* Info for last mouse motion */
50 static COORD movement_pos;
51 static Time movement_time;
52
53 /* from w32fns.c */
54 extern unsigned int map_keypad_keys (unsigned int, unsigned int);
55 extern unsigned int w32_key_to_modifier (int key);
56
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;
61
62 /* Temporarily store lead byte of DBCS input sequences. */
63 static char dbcs_lead = 0;
64
65 static inline BOOL
66 w32_read_console_input (HANDLE h, INPUT_RECORD *rec, DWORD recsize,
67 DWORD *waiting)
68 {
69 return (w32_console_unicode_input
70 ? ReadConsoleInputW (h, rec, recsize, waiting)
71 : ReadConsoleInputA (h, rec, recsize, waiting));
72 }
73
74 static int
75 fill_queue (BOOL block)
76 {
77 BOOL rc;
78 DWORD events_waiting;
79
80 if (queue_ptr < queue_end)
81 return queue_end-queue_ptr;
82
83 if (!block)
84 {
85 /* Check to see if there are some events to read before we try
86 because we can't block. */
87 if (!GetNumberOfConsoleInputEvents (keyboard_handle, &events_waiting))
88 return -1;
89 if (events_waiting == 0)
90 return 0;
91 }
92
93 rc = w32_read_console_input (keyboard_handle, event_queue, EVENT_QUEUE_SIZE,
94 &events_waiting);
95 if (!rc)
96 return -1;
97 queue_ptr = event_queue;
98 queue_end = event_queue + events_waiting;
99 return (int) events_waiting;
100 }
101
102 /* In a generic, multi-frame world this should take a console handle
103 and return the frame for it
104
105 Right now, there's only one frame so return it. */
106 static FRAME_PTR
107 get_frame (void)
108 {
109 return SELECTED_FRAME ();
110 }
111
112 /* Translate console modifiers to emacs modifiers.
113 German keyboard support (Kai Morgan Zeise 2/18/95). */
114 int
115 w32_kbd_mods_to_emacs (DWORD mods, WORD key)
116 {
117 int retval = 0;
118
119 /* If we recognize right-alt and left-ctrl as AltGr, and it has been
120 pressed, first remove those modifiers. */
121 if (!NILP (Vw32_recognize_altgr)
122 && (mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
123 == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED))
124 mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED);
125
126 if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
127 retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier);
128
129 if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
130 {
131 retval |= ctrl_modifier;
132 if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
133 == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
134 retval |= meta_modifier;
135 }
136
137 if (mods & LEFT_WIN_PRESSED)
138 retval |= w32_key_to_modifier (VK_LWIN);
139 if (mods & RIGHT_WIN_PRESSED)
140 retval |= w32_key_to_modifier (VK_RWIN);
141 if (mods & APPS_PRESSED)
142 retval |= w32_key_to_modifier (VK_APPS);
143 if (mods & SCROLLLOCK_ON)
144 retval |= w32_key_to_modifier (VK_SCROLL);
145
146 /* Just in case someone wanted the original behavior, make it
147 optional by setting w32-capslock-is-shiftlock to t. */
148 if (NILP (Vw32_capslock_is_shiftlock)
149 /* Keys that should _not_ be affected by CapsLock. */
150 && ( (key == VK_BACK)
151 || (key == VK_TAB)
152 || (key == VK_CLEAR)
153 || (key == VK_RETURN)
154 || (key == VK_ESCAPE)
155 || ((key >= VK_SPACE) && (key <= VK_HELP))
156 || ((key >= VK_NUMPAD0) && (key <= VK_F24))
157 || ((key >= VK_NUMPAD_CLEAR) && (key <= VK_NUMPAD_DELETE))
158 ))
159 {
160 /* Only consider shift state. */
161 if ((mods & SHIFT_PRESSED) != 0)
162 retval |= shift_modifier;
163 }
164 else
165 {
166 /* Ignore CapsLock state if not enabled. */
167 if (NILP (Vw32_enable_caps_lock))
168 mods &= ~CAPSLOCK_ON;
169 if ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) != 0)
170 retval |= shift_modifier;
171 }
172
173 return retval;
174 }
175
176 #if 0
177 /* Return nonzero if the virtual key is a dead key. */
178 static int
179 is_dead_key (int wparam)
180 {
181 unsigned int code = MapVirtualKey (wparam, 2);
182
183 /* Windows 95 returns 0x8000, NT returns 0x80000000. */
184 return (code & 0x80008000) ? 1 : 0;
185 }
186 #endif
187
188 /* The return code indicates key code size. cpID is the codepage to
189 use for translation to Unicode; -1 means use the current console
190 input codepage. */
191 int
192 w32_kbd_patch_key (KEY_EVENT_RECORD *event, int cpId)
193 {
194 unsigned int key_code = event->wVirtualKeyCode;
195 unsigned int mods = event->dwControlKeyState;
196 BYTE keystate[256];
197 static BYTE ansi_code[4];
198 static int isdead = 0;
199
200 if (isdead == 2)
201 {
202 event->uChar.AsciiChar = ansi_code[2];
203 isdead = 0;
204 return 1;
205 }
206 if (event->uChar.AsciiChar != 0)
207 return 1;
208
209 memset (keystate, 0, sizeof (keystate));
210 keystate[key_code] = 0x80;
211 if (mods & SHIFT_PRESSED)
212 keystate[VK_SHIFT] = 0x80;
213 if (mods & CAPSLOCK_ON)
214 keystate[VK_CAPITAL] = 1;
215 /* If we recognize right-alt and left-ctrl as AltGr, set the key
216 states accordingly before invoking ToAscii. */
217 if (!NILP (Vw32_recognize_altgr)
218 && (mods & LEFT_CTRL_PRESSED) && (mods & RIGHT_ALT_PRESSED))
219 {
220 keystate[VK_CONTROL] = 0x80;
221 keystate[VK_LCONTROL] = 0x80;
222 keystate[VK_MENU] = 0x80;
223 keystate[VK_RMENU] = 0x80;
224 }
225
226 #if 0
227 /* Because of an OS bug, ToAscii corrupts the stack when called to
228 convert a dead key in console mode on NT4. Unfortunately, trying
229 to check for dead keys using MapVirtualKey doesn't work either -
230 these functions apparently use internal information about keyboard
231 layout which doesn't get properly updated in console programs when
232 changing layout (though apparently it gets partly updated,
233 otherwise ToAscii wouldn't crash). */
234 if (is_dead_key (event->wVirtualKeyCode))
235 return 0;
236 #endif
237
238 /* On NT, call ToUnicode instead and then convert to the current
239 console input codepage. */
240 if (os_subtype == OS_NT)
241 {
242 WCHAR buf[128];
243
244 isdead = ToUnicode (event->wVirtualKeyCode, event->wVirtualScanCode,
245 keystate, buf, 128, 0);
246 if (isdead > 0)
247 {
248 /* When we are called from the GUI message processing code,
249 we are passed the current keyboard codepage, a positive
250 number, to use below. */
251 if (cpId == -1)
252 cpId = GetConsoleCP ();
253
254 event->uChar.UnicodeChar = buf[isdead - 1];
255 isdead = WideCharToMultiByte (cpId, 0, buf, isdead,
256 ansi_code, 4, NULL, NULL);
257 }
258 else
259 isdead = 0;
260 }
261 else
262 {
263 isdead = ToAscii (event->wVirtualKeyCode, event->wVirtualScanCode,
264 keystate, (LPWORD) ansi_code, 0);
265 }
266
267 if (isdead == 0)
268 return 0;
269 event->uChar.AsciiChar = ansi_code[0];
270 return isdead;
271 }
272
273
274 static int faked_key = 0;
275
276 /* return code -1 means that event_queue_ptr won't be incremented.
277 In other word, this event makes two key codes. (by himi) */
278 static int
279 key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
280 {
281 static int mod_key_state = 0;
282 int wParam;
283
284 *isdead = 0;
285
286 /* Skip key-up events. */
287 if (!event->bKeyDown)
288 {
289 switch (event->wVirtualKeyCode)
290 {
291 case VK_LWIN:
292 mod_key_state &= ~LEFT_WIN_PRESSED;
293 break;
294 case VK_RWIN:
295 mod_key_state &= ~RIGHT_WIN_PRESSED;
296 break;
297 case VK_APPS:
298 mod_key_state &= ~APPS_PRESSED;
299 break;
300 }
301 return 0;
302 }
303
304 /* Ignore keystrokes we fake ourself; see below. */
305 if (faked_key == event->wVirtualKeyCode)
306 {
307 faked_key = 0;
308 return 0;
309 }
310
311 /* To make it easier to debug this code, ignore modifier keys! */
312 switch (event->wVirtualKeyCode)
313 {
314 case VK_LWIN:
315 if (NILP (Vw32_pass_lwindow_to_system))
316 {
317 /* Prevent system from acting on keyup (which opens the Start
318 menu if no other key was pressed) by simulating a press of
319 Space which we will ignore. */
320 if ((mod_key_state & LEFT_WIN_PRESSED) == 0)
321 {
322 if (NUMBERP (Vw32_phantom_key_code))
323 faked_key = XUINT (Vw32_phantom_key_code) & 255;
324 else
325 faked_key = VK_SPACE;
326 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
327 }
328 }
329 mod_key_state |= LEFT_WIN_PRESSED;
330 if (!NILP (Vw32_lwindow_modifier))
331 return 0;
332 break;
333 case VK_RWIN:
334 if (NILP (Vw32_pass_rwindow_to_system))
335 {
336 if ((mod_key_state & RIGHT_WIN_PRESSED) == 0)
337 {
338 if (NUMBERP (Vw32_phantom_key_code))
339 faked_key = XUINT (Vw32_phantom_key_code) & 255;
340 else
341 faked_key = VK_SPACE;
342 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
343 }
344 }
345 mod_key_state |= RIGHT_WIN_PRESSED;
346 if (!NILP (Vw32_rwindow_modifier))
347 return 0;
348 break;
349 case VK_APPS:
350 mod_key_state |= APPS_PRESSED;
351 if (!NILP (Vw32_apps_modifier))
352 return 0;
353 break;
354 case VK_CAPITAL:
355 /* Decide whether to treat as modifier or function key. */
356 if (NILP (Vw32_enable_caps_lock))
357 goto disable_lock_key;
358 return 0;
359 case VK_NUMLOCK:
360 /* Decide whether to treat as modifier or function key. */
361 if (NILP (Vw32_enable_num_lock))
362 goto disable_lock_key;
363 return 0;
364 case VK_SCROLL:
365 /* Decide whether to treat as modifier or function key. */
366 if (NILP (Vw32_scroll_lock_modifier))
367 goto disable_lock_key;
368 return 0;
369 disable_lock_key:
370 /* Ensure the appropriate lock key state is off (and the
371 indicator light as well). */
372 wParam = event->wVirtualKeyCode;
373 if (GetAsyncKeyState (wParam) & 0x8000)
374 {
375 /* Fake another press of the relevant key. Apparently, this
376 really is the only way to turn off the indicator. */
377 faked_key = wParam;
378 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
379 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
380 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
381 KEYEVENTF_EXTENDEDKEY | 0, 0);
382 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
383 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
384 }
385 break;
386 case VK_MENU:
387 case VK_CONTROL:
388 case VK_SHIFT:
389 return 0;
390 case VK_CANCEL:
391 /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
392 which is confusing for purposes of key binding; convert
393 VK_CANCEL events into VK_PAUSE events. */
394 event->wVirtualKeyCode = VK_PAUSE;
395 break;
396 case VK_PAUSE:
397 /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
398 for purposes of key binding; convert these back into
399 VK_NUMLOCK events, at least when we want to see NumLock key
400 presses. (Note that there is never any possibility that
401 VK_PAUSE with Ctrl really is C-Pause as per above.) */
402 if (NILP (Vw32_enable_num_lock)
403 && (event->dwControlKeyState
404 & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0)
405 event->wVirtualKeyCode = VK_NUMLOCK;
406 break;
407 }
408
409 /* Recognize state of Windows and Apps keys. */
410 event->dwControlKeyState |= mod_key_state;
411
412 /* Distinguish numeric keypad keys from extended keys. */
413 event->wVirtualKeyCode =
414 map_keypad_keys (event->wVirtualKeyCode,
415 (event->dwControlKeyState & ENHANCED_KEY));
416
417 if (lispy_function_keys[event->wVirtualKeyCode] == 0)
418 {
419 if (!NILP (Vw32_recognize_altgr)
420 && (event->dwControlKeyState & LEFT_CTRL_PRESSED)
421 && (event->dwControlKeyState & RIGHT_ALT_PRESSED))
422 {
423 /* Don't try to interpret AltGr key chords; ToAscii seems not
424 to process them correctly. */
425 }
426 /* Handle key chords including any modifiers other than shift
427 directly, in order to preserve as much modifier information as
428 possible. */
429 else if (event->dwControlKeyState
430 & ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED
431 | RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED
432 | (!NILP (Vw32_lwindow_modifier) ? LEFT_WIN_PRESSED : 0)
433 | (!NILP (Vw32_rwindow_modifier) ? RIGHT_WIN_PRESSED : 0)
434 | (!NILP (Vw32_apps_modifier) ? APPS_PRESSED : 0)
435 | (!NILP (Vw32_scroll_lock_modifier) ? SCROLLLOCK_ON : 0)))
436 {
437 /* Don't translate modified alphabetic keystrokes, so the user
438 doesn't need to constantly switch layout to type control or
439 meta keystrokes when the normal layout translates
440 alphabetic characters to non-ascii characters. */
441 if ('A' <= event->wVirtualKeyCode && event->wVirtualKeyCode <= 'Z')
442 {
443 event->uChar.AsciiChar = event->wVirtualKeyCode;
444 if ((event->dwControlKeyState & SHIFT_PRESSED) == 0)
445 event->uChar.AsciiChar += ('a' - 'A');
446 }
447 /* Try to handle unrecognized keystrokes by determining the
448 base character (ie. translating the base key plus shift
449 modifier). */
450 else if (event->uChar.AsciiChar == 0)
451 w32_kbd_patch_key (event, -1);
452 }
453
454 if (event->uChar.AsciiChar == 0)
455 {
456 emacs_ev->kind = NO_EVENT;
457 return 0;
458 }
459 else if (event->uChar.AsciiChar > 0)
460 {
461 /* Pure ASCII characters < 128. */
462 emacs_ev->kind = ASCII_KEYSTROKE_EVENT;
463 emacs_ev->code = event->uChar.AsciiChar;
464 }
465 else if (event->uChar.UnicodeChar > 0
466 && w32_console_unicode_input)
467 {
468 /* Unicode codepoint; only valid if we are using Unicode
469 console input mode. */
470 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
471 emacs_ev->code = event->uChar.UnicodeChar;
472 }
473 else
474 {
475 /* Fallback handling of non-ASCII characters for non-Unicode
476 versions of Windows, and for non-Unicode input on NT
477 family of Windows. Only characters in the current
478 console codepage are supported by this fallback. */
479 wchar_t code;
480 char dbcs[2];
481 int cpId;
482
483 /* Get the current console input codepage to interpret this
484 key with. Note that the system defaults for the OEM
485 codepage could have been changed by calling SetConsoleCP
486 or w32-set-console-codepage, so using GetLocaleInfo to
487 get LOCALE_IDEFAULTCODEPAGE is not TRT here. */
488 cpId = GetConsoleCP ();
489
490 dbcs[0] = dbcs_lead;
491 dbcs[1] = event->uChar.AsciiChar;
492 if (dbcs_lead)
493 {
494 dbcs_lead = 0;
495 if (!MultiByteToWideChar (cpId, 0, dbcs, 2, &code, 1))
496 {
497 /* Garbage */
498 DebPrint (("Invalid DBCS sequence: %d %d\n",
499 dbcs[0], dbcs[1]));
500 emacs_ev->kind = NO_EVENT;
501 }
502 }
503 else if (IsDBCSLeadByteEx (cpId, dbcs[1]))
504 {
505 dbcs_lead = dbcs[1];
506 emacs_ev->kind = NO_EVENT;
507 }
508 else
509 {
510 if (!MultiByteToWideChar (cpId, 0, &dbcs[1], 1, &code, 1))
511 {
512 /* Garbage */
513 DebPrint (("Invalid character: %d\n", dbcs[1]));
514 emacs_ev->kind = NO_EVENT;
515 }
516 }
517 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
518 emacs_ev->code = code;
519 }
520 }
521 else
522 {
523 /* Function keys and other non-character keys. */
524 emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT;
525 emacs_ev->code = event->wVirtualKeyCode;
526 }
527
528 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
529 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState,
530 event->wVirtualKeyCode);
531 emacs_ev->timestamp = GetTickCount ();
532 return 1;
533 }
534
535 int
536 w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state)
537 {
538 int cur_state = (GetKeyState (vk_code) & 1);
539
540 if (NILP (new_state)
541 || (NUMBERP (new_state)
542 && ((XUINT (new_state)) & 1) != cur_state))
543 {
544 faked_key = vk_code;
545
546 keybd_event ((BYTE) vk_code,
547 (BYTE) MapVirtualKey (vk_code, 0),
548 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
549 keybd_event ((BYTE) vk_code,
550 (BYTE) MapVirtualKey (vk_code, 0),
551 KEYEVENTF_EXTENDEDKEY | 0, 0);
552 keybd_event ((BYTE) vk_code,
553 (BYTE) MapVirtualKey (vk_code, 0),
554 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
555 cur_state = !cur_state;
556 }
557
558 return cur_state;
559 }
560
561 /* Mouse position hook. */
562 void
563 w32_console_mouse_position (FRAME_PTR *f,
564 int insist,
565 Lisp_Object *bar_window,
566 enum scroll_bar_part *part,
567 Lisp_Object *x,
568 Lisp_Object *y,
569 Time *time)
570 {
571 BLOCK_INPUT;
572
573 insist = insist;
574
575 *f = get_frame ();
576 *bar_window = Qnil;
577 *part = 0;
578 SELECTED_FRAME ()->mouse_moved = 0;
579
580 XSETINT (*x, movement_pos.X);
581 XSETINT (*y, movement_pos.Y);
582 *time = movement_time;
583
584 UNBLOCK_INPUT;
585 }
586
587 /* Remember mouse motion and notify emacs. */
588 static void
589 mouse_moved_to (int x, int y)
590 {
591 /* If we're in the same place, ignore it. */
592 if (x != movement_pos.X || y != movement_pos.Y)
593 {
594 SELECTED_FRAME ()->mouse_moved = 1;
595 movement_pos.X = x;
596 movement_pos.Y = y;
597 movement_time = GetTickCount ();
598 }
599 }
600
601 /* Consoles return button bits in a strange order:
602 least significant - Leftmost button
603 next - Rightmost button
604 next - Leftmost+1
605 next - Leftmost+2...
606
607 Assume emacs likes three button mice, so
608 Left == 0
609 Middle == 1
610 Right == 2
611 Others increase from there. */
612
613 #define NUM_TRANSLATED_MOUSE_BUTTONS 3
614 static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] =
615 {
616 0, 2, 1
617 };
618
619 static int
620 do_mouse_event (MOUSE_EVENT_RECORD *event,
621 struct input_event *emacs_ev)
622 {
623 static DWORD button_state = 0;
624 static Lisp_Object last_mouse_window;
625 DWORD but_change, mask;
626 int i;
627
628 if (event->dwEventFlags == MOUSE_MOVED)
629 {
630 FRAME_PTR f = SELECTED_FRAME ();
631 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
632 int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y;
633
634 mouse_moved_to (mx, my);
635
636 if (f->mouse_moved)
637 {
638 if (hlinfo->mouse_face_hidden)
639 {
640 hlinfo->mouse_face_hidden = 0;
641 clear_mouse_face (hlinfo);
642 }
643
644 /* Generate SELECT_WINDOW_EVENTs when needed. */
645 if (!NILP (Vmouse_autoselect_window))
646 {
647 Lisp_Object mouse_window = window_from_coordinates (f, mx, my,
648 0, 0);
649 /* A window will be selected only when it is not
650 selected now, and the last mouse movement event was
651 not in it. A minibuffer window will be selected iff
652 it is active. */
653 if (WINDOWP (mouse_window)
654 && !EQ (mouse_window, last_mouse_window)
655 && !EQ (mouse_window, selected_window))
656 {
657 struct input_event event;
658
659 EVENT_INIT (event);
660 event.kind = SELECT_WINDOW_EVENT;
661 event.frame_or_window = mouse_window;
662 event.arg = Qnil;
663 event.timestamp = movement_time;
664 kbd_buffer_store_event (&event);
665 }
666 last_mouse_window = mouse_window;
667 }
668 else
669 last_mouse_window = Qnil;
670
671 previous_help_echo_string = help_echo_string;
672 help_echo_string = help_echo_object = help_echo_window = Qnil;
673 help_echo_pos = -1;
674 note_mouse_highlight (f, mx, my);
675 /* If the contents of the global variable help_echo has
676 changed (inside note_mouse_highlight), generate a HELP_EVENT. */
677 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
678 gen_help_event (help_echo_string, selected_frame, help_echo_window,
679 help_echo_object, help_echo_pos);
680 }
681 return 0;
682 }
683
684 /* It looks like the console code sends us a mouse event with
685 dwButtonState == 0 when a window is activated. Ignore this case. */
686 if (event->dwButtonState == button_state)
687 return 0;
688
689 emacs_ev->kind = MOUSE_CLICK_EVENT;
690
691 /* Find out what button has changed state since the last button event. */
692 but_change = button_state ^ event->dwButtonState;
693 mask = 1;
694 for (i = 0; mask; i++, mask <<= 1)
695 if (but_change & mask)
696 {
697 if (i < NUM_TRANSLATED_MOUSE_BUTTONS)
698 emacs_ev->code = emacs_button_translation[i];
699 else
700 emacs_ev->code = i;
701 break;
702 }
703
704 button_state = event->dwButtonState;
705 emacs_ev->timestamp = GetTickCount ();
706 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 0) |
707 ((event->dwButtonState & mask) ? down_modifier : up_modifier);
708
709 XSETFASTINT (emacs_ev->x, event->dwMousePosition.X);
710 XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y);
711 /* for Mule 2.2 (Based on Emacs 19.28 */
712 #ifdef MULE
713 XSET (emacs_ev->frame_or_window, Lisp_Frame, get_frame ());
714 #else
715 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
716 #endif
717
718 return 1;
719 }
720
721 static void
722 resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
723 {
724 FRAME_PTR f = get_frame ();
725
726 change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1, 0);
727 SET_FRAME_GARBAGED (f);
728 }
729
730 static void
731 maybe_generate_resize_event (void)
732 {
733 CONSOLE_SCREEN_BUFFER_INFO info;
734 FRAME_PTR f = get_frame ();
735
736 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
737
738 /* It is okay to call this unconditionally, since it will do nothing
739 if the size hasn't actually changed. */
740 change_frame_size (f,
741 1 + info.srWindow.Bottom - info.srWindow.Top,
742 1 + info.srWindow.Right - info.srWindow.Left,
743 0, 0, 0);
744 }
745
746 int
747 w32_console_read_socket (struct terminal *terminal,
748 int expected,
749 struct input_event *hold_quit)
750 {
751 int nev, ret = 0, add;
752 int isdead;
753
754 if (interrupt_input_blocked)
755 {
756 interrupt_input_pending = 1;
757 return -1;
758 }
759
760 interrupt_input_pending = 0;
761 BLOCK_INPUT;
762
763 for (;;)
764 {
765 nev = fill_queue (0);
766 if (nev <= 0)
767 {
768 /* If nev == -1, there was some kind of error
769 If nev == 0 then waitp must be zero and no events were available
770 so return. */
771 UNBLOCK_INPUT;
772 return nev;
773 }
774
775 while (nev > 0)
776 {
777 struct input_event inev;
778
779 EVENT_INIT (inev);
780 inev.kind = NO_EVENT;
781 inev.arg = Qnil;
782
783 switch (queue_ptr->EventType)
784 {
785 case KEY_EVENT:
786 add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead);
787 if (add == -1) /* 95.7.25 by himi */
788 {
789 queue_ptr--;
790 add = 1;
791 }
792 if (add)
793 kbd_buffer_store_event_hold (&inev, hold_quit);
794 break;
795
796 case MOUSE_EVENT:
797 add = do_mouse_event (&queue_ptr->Event.MouseEvent, &inev);
798 if (add)
799 kbd_buffer_store_event_hold (&inev, hold_quit);
800 break;
801
802 case WINDOW_BUFFER_SIZE_EVENT:
803 if (w32_use_full_screen_buffer)
804 resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
805 break;
806
807 case MENU_EVENT:
808 case FOCUS_EVENT:
809 /* Internal event types, ignored. */
810 break;
811 }
812
813 queue_ptr++;
814 nev--;
815 }
816
817 if (ret > 0 || expected == 0)
818 break;
819 }
820
821 /* We don't get told about changes in the window size (only the buffer
822 size, which we no longer care about), so we have to check it
823 periodically. */
824 if (!w32_use_full_screen_buffer)
825 maybe_generate_resize_event ();
826
827 UNBLOCK_INPUT;
828 return ret;
829 }