1 /* Input event support for Emacs on the Microsoft W32 API.
2 Copyright (C) 1992, 1993, 1995 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 2, or (at your option)
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; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
22 Adapted from ntkbd.c by Tim Fleehart
34 #include "blockinput.h"
35 #include "termhooks.h"
37 /* stdin, from ntterm */
38 extern HANDLE keyboard_handle
;
40 /* Info for last mouse motion */
41 static COORD movement_pos
;
42 static DWORD movement_time
;
45 extern void reinvoke_input_signal (void);
48 extern int change_frame_size (FRAME_PTR
, int, int, int, int);
51 extern Lisp_Object Vw32_alt_is_meta
;
54 extern Lisp_Object Vw32_capslock_is_shiftlock
;
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
;
62 fill_queue (BOOL block
)
67 if (queue_ptr
< queue_end
)
68 return queue_end
-queue_ptr
;
72 /* Check to see if there are some events to read before we try
73 because we can't block. */
74 if (!GetNumberOfConsoleInputEvents (keyboard_handle
, &events_waiting
))
76 if (events_waiting
== 0)
80 rc
= ReadConsoleInput (keyboard_handle
, event_queue
, EVENT_QUEUE_SIZE
,
84 queue_ptr
= event_queue
;
85 queue_end
= event_queue
+ events_waiting
;
86 return (int) events_waiting
;
89 /* In a generic, multi-frame world this should take a console handle
90 and return the frame for it
92 Right now, there's only one frame so return it. */
96 return selected_frame
;
99 /* Translate console modifiers to emacs modifiers.
100 German keyboard support (Kai Morgan Zeise 2/18/95). */
102 w32_kbd_mods_to_emacs (DWORD mods
, WORD key
)
106 /* If AltGr has been pressed, remove it. */
107 if ((mods
& (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
))
108 == (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
))
109 mods
&= ~ (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
);
111 if (mods
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
112 retval
= ((NILP (Vw32_alt_is_meta
)) ? alt_modifier
: meta_modifier
);
114 if (mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
116 retval
|= ctrl_modifier
;
117 if ((mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
118 == (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
119 retval
|= meta_modifier
;
122 /* Just in case someone wanted the original behaviour, make it
123 optional by setting w32-capslock-is-shiftlock to t. */
124 if (NILP (Vw32_capslock_is_shiftlock
)
125 && ((key
== VK_INSERT
)
126 || (key
== VK_DELETE
)
127 || ((key
>= VK_F1
) && (key
<= VK_F24
))
128 || ((key
>= VK_PRIOR
) && (key
<= VK_DOWN
))))
130 if ( (mods
& SHIFT_PRESSED
) == SHIFT_PRESSED
)
131 retval
|= shift_modifier
;
135 if (((mods
& (SHIFT_PRESSED
| CAPSLOCK_ON
)) == SHIFT_PRESSED
)
136 || ((mods
& (SHIFT_PRESSED
| CAPSLOCK_ON
)) == CAPSLOCK_ON
))
137 retval
|= shift_modifier
;
143 /* The return code indicates key code size. */
145 w32_kbd_patch_key (KEY_EVENT_RECORD
*event
)
147 unsigned int key_code
= event
->wVirtualKeyCode
;
148 unsigned int mods
= event
->dwControlKeyState
;
150 static BYTE ansi_code
[4];
151 static int isdead
= 0;
155 event
->uChar
.AsciiChar
= ansi_code
[2];
159 if (event
->uChar
.AsciiChar
!= 0)
162 memset (keystate
, 0, sizeof (keystate
));
163 if (mods
& SHIFT_PRESSED
)
164 keystate
[VK_SHIFT
] = 0x80;
165 if (mods
& CAPSLOCK_ON
)
166 keystate
[VK_CAPITAL
] = 1;
167 if ((mods
& LEFT_CTRL_PRESSED
) && (mods
& RIGHT_ALT_PRESSED
))
169 keystate
[VK_CONTROL
] = 0x80;
170 keystate
[VK_LCONTROL
] = 0x80;
171 keystate
[VK_MENU
] = 0x80;
172 keystate
[VK_RMENU
] = 0x80;
175 isdead
= ToAscii (event
->wVirtualKeyCode
, event
->wVirtualScanCode
,
176 keystate
, (LPWORD
) ansi_code
, 0);
179 event
->uChar
.AsciiChar
= ansi_code
[0];
183 /* Map virtual key codes into:
186 Other - Map non-ASCII keys into X keysyms so that they are looked up
187 correctly in keyboard.c
189 Return, escape and tab are mapped to ASCII rather than coming back
190 as non-ASCII to be more compatible with old-style keyboard support. */
192 static int map_virt_key
[256] =
201 0x69, /* VK_CANCEL */
215 -1, -1, -1, -1, -1, -1,
227 0x60, /* VK_SELECT */
229 0x62, /* VK_EXECUTE */
230 -1, /* VK_SNAPSHOT */
231 0x63, /* VK_INSERT */
232 0xff, /* VK_DELETE */
234 -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, /* 0 - 9 */
235 -1, -1, -1, -1, -1, -1, -1,
236 -2, -2, -2, -2, -2, -2, -2, -2, /* A - Z */
237 -2, -2, -2, -2, -2, -2, -2, -2,
238 -2, -2, -2, -2, -2, -2, -2, -2,
241 0xb0, /* VK_NUMPAD0 */
242 0xb1, /* VK_NUMPAD1 */
243 0xb2, /* VK_NUMPAD2 */
244 0xb3, /* VK_NUMPAD3 */
245 0xb4, /* VK_NUMPAD4 */
246 0xb5, /* VK_NUMPAD5 */
247 0xb6, /* VK_NUMPAD6 */
248 0xb7, /* VK_NUMPAD7 */
249 0xb8, /* VK_NUMPAD8 */
250 0xb9, /* VK_NUMPAD9 */
251 0xaa, /* VK_MULTIPLY */
253 0xac, /* VK_SEPARATOR */
254 0xad, /* VK_SUBTRACT */
255 0xae, /* VK_DECIMAL */
256 0xaf, /* VK_DIVIDE */
281 -1, -1, -1, -1, -1, -1, -1, -1,
282 0x7f, /* VK_NUMLOCK */
283 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9f */
284 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xaf */
285 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb9 */
293 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xcf */
294 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xda */
295 -2, -2, -2, -2, -2, /* 0xdf */
300 -2, -2, -2, -2, -2, -2, -2, /* 0xef */
301 -2, -2, -2, -2, -2, -2,
302 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xff */
305 /* return code -1 means that event_queue_ptr won't be incremented.
306 In other word, this event makes two key codes. (by himi) */
308 key_event (KEY_EVENT_RECORD
*event
, struct input_event
*emacs_ev
, int *isdead
)
312 static BOOL map_virt_key_init_done
;
316 /* Skip key-up events. */
317 if (!event
->bKeyDown
)
320 if (event
->wVirtualKeyCode
> 0xff)
322 printf ("Unknown key code %d\n", event
->wVirtualKeyCode
);
326 /* Patch needed for German keyboard. Ulrich Leodolter (1/11/95). */
327 if (! map_virt_key_init_done
)
331 if ((vk
= VkKeyScan (0x3c)) >= 0 && vk
< 256) map_virt_key
[vk
] = -2; /* less */
332 if ((vk
= VkKeyScan (0x3e)) >= 0 && vk
< 256) map_virt_key
[vk
] = -2; /* greater */
334 map_virt_key_init_done
= TRUE
;
337 /* BUGBUG - Ignores the repeat count
338 It's questionable whether we want to obey the repeat count anyway
339 since keys usually aren't repeated unless key events back up in
340 the queue. If they're backing up then we don't generally want
341 to honor them later since that leads to significant slop in
342 cursor motion when the system is under heavy load. */
344 map
= map_virt_key
[event
->wVirtualKeyCode
];
352 emacs_ev
->kind
= ascii_keystroke
;
353 key_flag
= w32_kbd_patch_key (event
); /* 95.7.25 by himi */
358 XSETINT (emacs_ev
->code
, event
->uChar
.AsciiChar
);
364 if ((event
->dwControlKeyState
& NLS_IME_CONVERSION
)
365 && !(event
->dwControlKeyState
& RIGHT_ALT_PRESSED
)
366 && !(event
->dwControlKeyState
& LEFT_ALT_PRESSED
)
367 && !(event
->dwControlKeyState
& RIGHT_CTRL_PRESSED
)
368 && !(event
->dwControlKeyState
& LEFT_CTRL_PRESSED
))
370 emacs_ev
->kind
= ascii_keystroke
;
371 XSETINT (emacs_ev
->code
, event
->uChar
.AsciiChar
);
380 emacs_ev
->kind
= non_ascii_keystroke
;
382 /* use Windows keysym map */
383 XSETINT (emacs_ev
->code
, event
->wVirtualKeyCode
);
386 * make_lispy_event () now requires non-ascii codes to have
387 * the full X keysym values (2nd byte is 0xff). add it on.
390 XSETINT (emacs_ev
->code
, map
);
391 #endif /* HAVE_NTGUI */
393 /* for Mule 2.2 (Based on Emacs 19.28) */
395 XSET (emacs_ev
->frame_or_window
, Lisp_Frame
, get_frame ());
397 XSETFRAME (emacs_ev
->frame_or_window
, get_frame ());
399 emacs_ev
->modifiers
= w32_kbd_mods_to_emacs (event
->dwControlKeyState
,
400 event
->wVirtualKeyCode
);
401 emacs_ev
->timestamp
= GetTickCount ();
402 if (key_flag
== 2) return -1; /* 95.7.25 by himi */
406 /* Mouse position hook. */
408 w32_mouse_position (FRAME_PTR
*f
,
412 Lisp_Object
*bar_window
,
413 enum scroll_bar_part
*part
,
427 selected_frame
->mouse_moved
= 0;
431 *time
= movement_time
;
436 /* Remember mouse motion and notify emacs. */
438 mouse_moved_to (int x
, int y
)
440 /* If we're in the same place, ignore it */
441 if (x
!= movement_pos
.X
|| y
!= movement_pos
.Y
)
443 selected_frame
->mouse_moved
= 1;
446 movement_time
= GetTickCount ();
450 /* Consoles return button bits in a strange order:
451 least significant - Leftmost button
452 next - Rightmost button
456 Assume emacs likes three button mice, so
460 Others increase from there. */
462 static int emacs_button_translation
[NUM_MOUSE_BUTTONS
] =
468 do_mouse_event (MOUSE_EVENT_RECORD
*event
,
469 struct input_event
*emacs_ev
)
471 static DWORD button_state
= 0;
472 DWORD but_change
, mask
;
475 if (event
->dwEventFlags
== MOUSE_MOVED
)
477 /* For movement events we just note that the mouse has moved
478 so that emacs will generate drag events. */
479 mouse_moved_to (event
->dwMousePosition
.X
, event
->dwMousePosition
.Y
);
483 /* It looks like the console code sends us a mouse event with
484 dwButtonState == 0 when a window is activated. Ignore this case. */
485 if (event
->dwButtonState
== button_state
)
488 emacs_ev
->kind
= mouse_click
;
490 /* Find out what button has changed state since the last button event. */
491 but_change
= button_state
^ event
->dwButtonState
;
493 for (i
= 0; i
< NUM_MOUSE_BUTTONS
; i
++, mask
<<= 1)
494 if (but_change
& mask
)
496 XSETINT (emacs_ev
->code
, emacs_button_translation
[i
]);
500 /* If the changed button is out of emacs' range (highly unlikely)
501 ignore this event. */
502 if (i
== NUM_MOUSE_BUTTONS
)
505 button_state
= event
->dwButtonState
;
506 emacs_ev
->timestamp
= GetTickCount ();
507 emacs_ev
->modifiers
= w32_kbd_mods_to_emacs (event
->dwControlKeyState
, 0) |
508 ((event
->dwButtonState
& mask
) ? down_modifier
: up_modifier
);
510 XSETFASTINT (emacs_ev
->x
, event
->dwMousePosition
.X
);
511 XSETFASTINT (emacs_ev
->y
, event
->dwMousePosition
.Y
);
512 /* for Mule 2.2 (Based on Emacs 19.28 */
514 XSET (emacs_ev
->frame_or_window
, Lisp_Frame
, get_frame ());
516 XSETFRAME (emacs_ev
->frame_or_window
, get_frame ());
523 resize_event (WINDOW_BUFFER_SIZE_RECORD
*event
)
525 FRAME_PTR f
= get_frame ();
527 change_frame_size (f
, event
->dwSize
.Y
, event
->dwSize
.X
, 0, 1);
528 SET_FRAME_GARBAGED (f
);
532 w32_console_read_socket (int sd
, struct input_event
*bufp
, int numchars
,
533 int waitp
, int expected
)
535 BOOL no_events
= TRUE
;
536 int nev
, ret
= 0, add
;
539 if (interrupt_input_blocked
)
541 interrupt_input_pending
= 1;
545 interrupt_input_pending
= 0;
550 nev
= fill_queue (0);
553 /* If nev == -1, there was some kind of error
554 If nev == 0 then waitp must be zero and no events were available
560 while (nev
> 0 && numchars
> 0)
562 switch (queue_ptr
->EventType
)
565 add
= key_event (&queue_ptr
->Event
.KeyEvent
, bufp
, &isdead
);
566 if (add
== -1) /* 95.7.25 by himi */
577 add
= do_mouse_event (&queue_ptr
->Event
.MouseEvent
, bufp
);
583 case WINDOW_BUFFER_SIZE_EVENT
:
584 resize_event (&queue_ptr
->Event
.WindowBufferSizeEvent
);
589 /* Internal event types, ignored. */
597 if (ret
> 0 || expected
== 0)