This source file includes following definitions.
- w32_read_console_input
- fill_queue
- get_frame
- is_dead_key
- key_event
- w32_console_mouse_position
- mouse_moved_to
- do_mouse_event
- resize_event
- maybe_generate_resize_event
- handle_file_notifications
- handle_file_notifications
- w32_console_read_socket
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 #include <config.h>
27 #include <stdio.h>
28 #include <windows.h>
29
30 #ifndef MOUSE_MOVED
31 #define MOUSE_MOVED 1
32 #endif
33 #ifndef MOUSE_HWHEELED
34 #define MOUSE_HWHEELED 8
35 #endif
36
37 #include "lisp.h"
38 #include "keyboard.h"
39 #include "frame.h"
40 #include "blockinput.h"
41 #include "termchar.h"
42 #include "w32term.h"
43 #include "w32inevt.h"
44 #include "w32common.h"
45
46
47 extern HANDLE keyboard_handle;
48
49
50 static COORD movement_pos;
51 static Time movement_time;
52
53
54 extern unsigned int map_keypad_keys (unsigned int, unsigned int);
55 extern unsigned int w32_key_to_modifier (int key);
56
57
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
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
75 int faked_key;
76
77 static int
78 fill_queue (BOOL block)
79 {
80 BOOL rc;
81 DWORD events_waiting;
82
83 if (queue_ptr < queue_end)
84 return queue_end-queue_ptr;
85
86 if (!block)
87 {
88
89
90 if (!GetNumberOfConsoleInputEvents (keyboard_handle, &events_waiting))
91 return -1;
92 if (events_waiting == 0)
93 return 0;
94 }
95
96 rc = w32_read_console_input (keyboard_handle, event_queue, EVENT_QUEUE_SIZE,
97 &events_waiting);
98 if (!rc)
99 return -1;
100 queue_ptr = event_queue;
101 queue_end = event_queue + events_waiting;
102 return (int) events_waiting;
103 }
104
105
106
107
108
109 static struct frame *
110 get_frame (void)
111 {
112 return SELECTED_FRAME ();
113 }
114
115
116
117
118
119 #if 0
120
121 static int
122 is_dead_key (int wparam)
123 {
124 unsigned int code = MapVirtualKey (wparam, 2);
125
126
127 return (code & 0x80008000) ? 1 : 0;
128 }
129 #endif
130
131
132
133
134
135
136
137
138 static int
139 key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
140 {
141 static int mod_key_state = 0;
142 int wParam;
143
144 *isdead = 0;
145
146
147 if (!event->bKeyDown)
148 {
149 switch (event->wVirtualKeyCode)
150 {
151 case VK_LWIN:
152 if (!w32_kbdhook_active)
153 mod_key_state &= ~LEFT_WIN_PRESSED;
154 break;
155 case VK_RWIN:
156 if (!w32_kbdhook_active)
157 mod_key_state &= ~RIGHT_WIN_PRESSED;
158 break;
159 case VK_APPS:
160 mod_key_state &= ~APPS_PRESSED;
161 break;
162 }
163 return 0;
164 }
165
166
167 if (faked_key == event->wVirtualKeyCode)
168 {
169 faked_key = 0;
170 return 0;
171 }
172
173
174 switch (event->wVirtualKeyCode)
175 {
176 case VK_LWIN:
177 if (NILP (Vw32_pass_lwindow_to_system))
178 {
179
180
181
182 if ((mod_key_state & LEFT_WIN_PRESSED) == 0)
183 {
184 if (FIXNUMP (Vw32_phantom_key_code))
185 faked_key = XUFIXNUM (Vw32_phantom_key_code) & 255;
186 else
187 faked_key = VK_SPACE;
188 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
189 }
190 }
191 if (!w32_kbdhook_active)
192 mod_key_state |= LEFT_WIN_PRESSED;
193 if (!NILP (Vw32_lwindow_modifier))
194 return 0;
195 break;
196 case VK_RWIN:
197 if (NILP (Vw32_pass_rwindow_to_system))
198 {
199 if ((mod_key_state & RIGHT_WIN_PRESSED) == 0)
200 {
201 if (FIXNUMP (Vw32_phantom_key_code))
202 faked_key = XUFIXNUM (Vw32_phantom_key_code) & 255;
203 else
204 faked_key = VK_SPACE;
205 keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
206 }
207 }
208 if (!w32_kbdhook_active)
209 mod_key_state |= RIGHT_WIN_PRESSED;
210 if (!NILP (Vw32_rwindow_modifier))
211 return 0;
212 break;
213 case VK_APPS:
214 mod_key_state |= APPS_PRESSED;
215 if (!NILP (Vw32_apps_modifier))
216 return 0;
217 break;
218 case VK_CAPITAL:
219
220 if (NILP (Vw32_enable_caps_lock))
221 goto disable_lock_key;
222 return 0;
223 case VK_NUMLOCK:
224
225 if (NILP (Vw32_enable_num_lock))
226 goto disable_lock_key;
227 return 0;
228 case VK_SCROLL:
229
230 if (NILP (Vw32_scroll_lock_modifier))
231 goto disable_lock_key;
232 return 0;
233 disable_lock_key:
234
235
236 wParam = event->wVirtualKeyCode;
237 if (GetAsyncKeyState (wParam) & 0x8000)
238 {
239
240
241 faked_key = wParam;
242 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
243 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
244 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
245 KEYEVENTF_EXTENDEDKEY | 0, 0);
246 keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
247 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
248 }
249 break;
250 case VK_MENU:
251 case VK_CONTROL:
252 case VK_SHIFT:
253 return 0;
254 case VK_CANCEL:
255
256
257
258 event->wVirtualKeyCode = VK_PAUSE;
259 break;
260 case VK_PAUSE:
261
262
263
264
265
266 if (NILP (Vw32_enable_num_lock)
267 && (event->dwControlKeyState
268 & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0)
269 event->wVirtualKeyCode = VK_NUMLOCK;
270 break;
271 }
272
273
274 event->dwControlKeyState |= mod_key_state;
275 if (w32_kbdhook_active)
276 {
277 if (check_w32_winkey_state (VK_LWIN))
278 event->dwControlKeyState |= LEFT_WIN_PRESSED;
279 if (check_w32_winkey_state (VK_RWIN))
280 event->dwControlKeyState |= RIGHT_WIN_PRESSED;
281 }
282
283
284 event->wVirtualKeyCode =
285 map_keypad_keys (event->wVirtualKeyCode,
286 (event->dwControlKeyState & ENHANCED_KEY));
287
288 if (lispy_function_keys[event->wVirtualKeyCode] == 0)
289 {
290 if (!NILP (Vw32_recognize_altgr)
291 && (event->dwControlKeyState & LEFT_CTRL_PRESSED)
292 && (event->dwControlKeyState & RIGHT_ALT_PRESSED))
293 {
294
295
296 }
297
298
299
300 else if (event->dwControlKeyState
301 & ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED
302 | RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED
303 | (!NILP (Vw32_lwindow_modifier) ? LEFT_WIN_PRESSED : 0)
304 | (!NILP (Vw32_rwindow_modifier) ? RIGHT_WIN_PRESSED : 0)
305 | (!NILP (Vw32_apps_modifier) ? APPS_PRESSED : 0)
306 | (!NILP (Vw32_scroll_lock_modifier) ? SCROLLLOCK_ON : 0)))
307 {
308
309
310
311
312 if ('A' <= event->wVirtualKeyCode && event->wVirtualKeyCode <= 'Z')
313 {
314 event->uChar.AsciiChar = event->wVirtualKeyCode;
315 if ((event->dwControlKeyState & SHIFT_PRESSED) == 0)
316 event->uChar.AsciiChar += ('a' - 'A');
317 }
318
319
320
321 else if (event->uChar.AsciiChar == 0)
322 w32_kbd_patch_key (event, -1);
323 }
324
325 if (event->uChar.AsciiChar == 0)
326 {
327 emacs_ev->kind = NO_EVENT;
328 return 0;
329 }
330 else if (event->uChar.AsciiChar > 0)
331 {
332
333 emacs_ev->kind = ASCII_KEYSTROKE_EVENT;
334 emacs_ev->code = event->uChar.AsciiChar;
335 }
336 else if (event->uChar.UnicodeChar > 0
337 && w32_console_unicode_input)
338 {
339
340
341 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
342 emacs_ev->code = event->uChar.UnicodeChar;
343 }
344 else
345 {
346
347
348
349
350 wchar_t code;
351 char dbcs[2];
352 int cpId;
353
354
355
356
357
358
359 cpId = GetConsoleCP ();
360
361 dbcs[0] = dbcs_lead;
362 dbcs[1] = event->uChar.AsciiChar;
363 if (dbcs_lead)
364 {
365 dbcs_lead = 0;
366 if (!MultiByteToWideChar (cpId, 0, dbcs, 2, &code, 1))
367 {
368
369 DebPrint (("Invalid DBCS sequence: %d %d\n",
370 dbcs[0], dbcs[1]));
371 emacs_ev->kind = NO_EVENT;
372 }
373 }
374 else if (IsDBCSLeadByteEx (cpId, dbcs[1]))
375 {
376 dbcs_lead = dbcs[1];
377 emacs_ev->kind = NO_EVENT;
378 }
379 else
380 {
381 if (!MultiByteToWideChar (cpId, 0, &dbcs[1], 1, &code, 1))
382 {
383
384 DebPrint (("Invalid character: %d\n", dbcs[1]));
385 emacs_ev->kind = NO_EVENT;
386 }
387 }
388 emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
389 emacs_ev->code = code;
390 }
391 }
392 else
393 {
394
395 emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT;
396 emacs_ev->code = event->wVirtualKeyCode;
397 }
398
399 XSETFRAME (emacs_ev->frame_or_window, get_frame ());
400 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState,
401 event->wVirtualKeyCode);
402 emacs_ev->timestamp = GetTickCount ();
403 return 1;
404 }
405
406
407 void
408 w32_console_mouse_position (struct frame **f,
409 int insist,
410 Lisp_Object *bar_window,
411 enum scroll_bar_part *part,
412 Lisp_Object *x,
413 Lisp_Object *y,
414 Time *time)
415 {
416 block_input ();
417
418 insist = insist;
419
420 *f = get_frame ();
421 *bar_window = Qnil;
422 *part = scroll_bar_above_handle;
423 (*f)->mouse_moved = 0;
424
425 XSETINT (*x, movement_pos.X);
426 XSETINT (*y, movement_pos.Y);
427 *time = movement_time;
428
429 unblock_input ();
430 }
431
432
433 static void
434 mouse_moved_to (int x, int y)
435 {
436
437 if (x != movement_pos.X || y != movement_pos.Y)
438 {
439 struct frame *f = get_frame ();
440 f->mouse_moved = 1;
441 movement_pos.X = x;
442 movement_pos.Y = y;
443 movement_time = GetTickCount ();
444 }
445 }
446
447
448
449
450
451
452
453
454
455
456
457
458
459 #define NUM_TRANSLATED_MOUSE_BUTTONS 5
460 static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] =
461 {
462 0, 2, 1, 3, 4
463 };
464
465 static int
466 do_mouse_event (MOUSE_EVENT_RECORD *event,
467 struct input_event *emacs_ev)
468 {
469 static DWORD button_state = 0;
470 static Lisp_Object last_mouse_window;
471 DWORD but_change, mask, flags = event->dwEventFlags;
472 int i;
473
474
475 struct frame *f = get_frame ();
476 f->mouse_moved = 0;
477
478 switch (flags)
479 {
480 case MOUSE_MOVED:
481 {
482 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
483 int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y;
484
485 mouse_moved_to (mx, my);
486
487 if (f->mouse_moved)
488 {
489 if (hlinfo->mouse_face_hidden)
490 {
491 hlinfo->mouse_face_hidden = 0;
492 clear_mouse_face (hlinfo);
493 }
494
495
496 if (!NILP (Vmouse_autoselect_window))
497 {
498 Lisp_Object mouse_window = window_from_coordinates (f, mx, my,
499 0, 0, 0);
500
501
502
503
504 if (WINDOWP (mouse_window)
505 && !EQ (mouse_window, last_mouse_window)
506 && !EQ (mouse_window, selected_window))
507 {
508 struct input_event event;
509
510 EVENT_INIT (event);
511 event.kind = SELECT_WINDOW_EVENT;
512 event.frame_or_window = mouse_window;
513 event.arg = Qnil;
514 event.timestamp = movement_time;
515 kbd_buffer_store_event (&event);
516 }
517 last_mouse_window = mouse_window;
518 }
519 else
520 last_mouse_window = Qnil;
521
522 previous_help_echo_string = help_echo_string;
523 help_echo_string = help_echo_object = help_echo_window = Qnil;
524 help_echo_pos = -1;
525 note_mouse_highlight (f, mx, my);
526
527
528 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
529 gen_help_event (help_echo_string, selected_frame,
530 help_echo_window, help_echo_object,
531 help_echo_pos);
532 }
533
534
535 return 0;
536 }
537 case MOUSE_WHEELED:
538 case MOUSE_HWHEELED:
539 {
540
541
542
543
544
545
546 int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y;
547 bool down_p = (event->dwButtonState & 0x10000000) != 0;
548
549 emacs_ev->kind =
550 flags == MOUSE_HWHEELED ? HORIZ_WHEEL_EVENT : WHEEL_EVENT;
551 emacs_ev->code = 0;
552 emacs_ev->modifiers = down_p ? down_modifier : up_modifier;
553 emacs_ev->modifiers |=
554 w32_kbd_mods_to_emacs (event->dwControlKeyState, 0);
555 XSETINT (emacs_ev->x, mx);
556 XSETINT (emacs_ev->y, my);
557 XSETFRAME (emacs_ev->frame_or_window, f);
558 emacs_ev->arg = Qnil;
559 emacs_ev->timestamp = GetTickCount ();
560 return 1;
561 }
562 case DOUBLE_CLICK:
563 default:
564
565
566
567
568 if (event->dwButtonState == button_state)
569 return 0;
570
571
572
573 but_change = button_state ^ event->dwButtonState;
574 mask = 1;
575 for (i = 0; mask; i++, mask <<= 1)
576 if (but_change & mask)
577 {
578 if (i < NUM_TRANSLATED_MOUSE_BUTTONS)
579 emacs_ev->code = emacs_button_translation[i];
580 else
581 emacs_ev->code = i;
582 break;
583 }
584
585 button_state = event->dwButtonState;
586 emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 0);
587 emacs_ev->timestamp = GetTickCount ();
588
589 int x = event->dwMousePosition.X;
590 int y = event->dwMousePosition.Y;
591 emacs_ev->arg = tty_handle_tab_bar_click (f, x, y,
592 (button_state & mask) != 0,
593 emacs_ev);
594
595 emacs_ev->modifiers |= ((button_state & mask)
596 ? down_modifier : up_modifier);
597
598 emacs_ev->kind = MOUSE_CLICK_EVENT;
599 XSETFASTINT (emacs_ev->x, x);
600 XSETFASTINT (emacs_ev->y, y);
601 XSETFRAME (emacs_ev->frame_or_window, f);
602
603 return 1;
604 }
605 }
606
607 static void
608 resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
609 {
610 struct frame *f = get_frame ();
611
612 change_frame_size (f, event->dwSize.X, event->dwSize.Y, false, true, false);
613 SET_FRAME_GARBAGED (f);
614 }
615
616 static void
617 maybe_generate_resize_event (void)
618 {
619 CONSOLE_SCREEN_BUFFER_INFO info;
620 struct frame *f = get_frame ();
621
622 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
623
624
625
626 change_frame_size (f, 1 + info.srWindow.Right - info.srWindow.Left,
627 1 + info.srWindow.Bottom - info.srWindow.Top,
628 false, true, false);
629 }
630
631 #if HAVE_W32NOTIFY
632 int
633 handle_file_notifications (struct input_event *hold_quit)
634 {
635 struct notifications_set *ns = NULL;
636 int nevents = 0;
637 int done = 0;
638
639
640
641 if (!initialized)
642 {
643 return nevents;
644 }
645
646 while (!done)
647 {
648 ns = NULL;
649
650
651
652
653 enter_crit ();
654 if (notifications_set_head->next != notifications_set_head)
655 {
656 ns = notifications_set_head->next;
657 ns->prev->next = ns->next;
658 ns->next->prev = ns->prev;
659 }
660 else
661 done = 1;
662 leave_crit();
663
664 if (ns)
665 {
666 BYTE *p = ns->notifications;
667 FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p;
668 const DWORD min_size
669 = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t);
670 struct input_event inev;
671 DWORD info_size = ns->size;
672 Lisp_Object cs = Qutf_16le;
673 Lisp_Object obj = w32_get_watch_object (ns->desc);
674
675
676
677
678
679 if (info_size
680 && !NILP (obj) && CONSP (obj))
681 {
682 Lisp_Object callback = XCDR (obj);
683
684 EVENT_INIT (inev);
685
686 while (info_size >= min_size)
687 {
688 Lisp_Object utf_16_fn
689 = make_unibyte_string ((char *)fni->FileName,
690 fni->FileNameLength);
691
692
693 Lisp_Object fname
694 = code_convert_string_norecord (utf_16_fn, cs, 0);
695 Lisp_Object action = w32_lispy_file_action (fni->Action);
696
697 inev.kind = FILE_NOTIFY_EVENT;
698 inev.timestamp = GetTickCount ();
699 inev.modifiers = 0;
700 inev.frame_or_window = callback;
701 inev.arg = Fcons (action, fname);
702 inev.arg = list3 (make_pointer_integer (ns->desc),
703 action, fname);
704 kbd_buffer_store_event_hold (&inev, hold_quit);
705 nevents++;
706 if (!fni->NextEntryOffset)
707 break;
708 p += fni->NextEntryOffset;
709 fni = (PFILE_NOTIFY_INFORMATION)p;
710 info_size -= fni->NextEntryOffset;
711 }
712 }
713
714 free (ns->notifications);
715 free (ns);
716 }
717 }
718 return nevents;
719 }
720 #else
721 int
722 handle_file_notifications (struct input_event *hold_quit)
723 {
724 return 0;
725 }
726 #endif
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760 int
761 w32_console_read_socket (struct terminal *terminal,
762 struct input_event *hold_quit)
763 {
764 int nev, add;
765 int isdead;
766
767 block_input ();
768
769 for (;;)
770 {
771 int nfnotify = handle_file_notifications (hold_quit);
772
773 nev = fill_queue (0);
774 if (nev <= 0)
775 {
776
777
778
779 if (nfnotify)
780 nev = 0;
781 break;
782 }
783
784 while (nev > 0)
785 {
786 struct input_event inev;
787
788
789
790
791 unsigned evtype = queue_ptr->EventType;
792
793 EVENT_INIT (inev);
794 inev.kind = NO_EVENT;
795 inev.arg = Qnil;
796
797 switch (evtype)
798 {
799 case KEY_EVENT:
800 add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead);
801 if (add == -1)
802 {
803 queue_ptr--;
804 add = 1;
805 }
806 if (add)
807 kbd_buffer_store_event_hold (&inev, hold_quit);
808 break;
809
810 case MOUSE_EVENT:
811 add = do_mouse_event (&queue_ptr->Event.MouseEvent, &inev);
812 if (add)
813 kbd_buffer_store_event_hold (&inev, hold_quit);
814 break;
815
816 case WINDOW_BUFFER_SIZE_EVENT:
817 if (w32_use_full_screen_buffer)
818 resize_event (&queue_ptr->Event.WindowBufferSizeEvent);
819 break;
820
821 case MENU_EVENT:
822 case FOCUS_EVENT:
823
824 break;
825 }
826
827 queue_ptr++;
828 nev--;
829 }
830 }
831
832
833
834
835 if (!w32_use_full_screen_buffer)
836 maybe_generate_resize_event ();
837
838 unblock_input ();
839 return nev;
840 }