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