1 /* Input event support for Windows NT port of GNU Emacs.
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 #define EVENT_QUEUE_SIZE 50
52 static INPUT_RECORD event_queue
[EVENT_QUEUE_SIZE
];
53 static INPUT_RECORD
*queue_ptr
= event_queue
, *queue_end
= event_queue
;
56 fill_queue (BOOL block
)
61 if (queue_ptr
< queue_end
)
62 return queue_end
-queue_ptr
;
66 /* Check to see if there are some events to read before we try
67 because we can't block. */
68 if (!GetNumberOfConsoleInputEvents (keyboard_handle
, &events_waiting
))
70 if (events_waiting
== 0)
74 rc
= ReadConsoleInput (keyboard_handle
, event_queue
, EVENT_QUEUE_SIZE
,
78 queue_ptr
= event_queue
;
79 queue_end
= event_queue
+ events_waiting
;
80 return (int) events_waiting
;
83 /* In a generic, multi-frame world this should take a console handle
84 and return the frame for it
86 Right now, there's only one frame so return it. */
90 return selected_frame
;
93 /* Translate console modifiers to emacs modifiers.
94 German keyboard support (Kai Morgan Zeise 2/18/95). */
96 win32_kbd_mods_to_emacs (DWORD mods
)
100 /* If AltGr has been pressed, remove it. */
101 if ((mods
& (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
))
102 == (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
))
103 mods
&= ~ (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
);
105 if (mods
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
106 retval
= meta_modifier
;
108 if (mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
110 retval
|= ctrl_modifier
;
111 if ((mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
112 == (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
113 retval
|= meta_modifier
;
116 if (((mods
& (SHIFT_PRESSED
| CAPSLOCK_ON
)) == SHIFT_PRESSED
)
117 || ((mods
& (SHIFT_PRESSED
| CAPSLOCK_ON
)) == CAPSLOCK_ON
))
118 retval
|= shift_modifier
;
123 /* The return code indicates key code size. */
125 win32_kbd_patch_key (KEY_EVENT_RECORD
*event
)
127 unsigned int key_code
= event
->wVirtualKeyCode
;
128 unsigned int mods
= event
->dwControlKeyState
;
130 static BYTE ansi_code
[4];
131 static int isdead
= 0;
135 event
->uChar
.AsciiChar
= ansi_code
[2];
139 if (event
->uChar
.AsciiChar
!= 0)
142 memset (keystate
, 0, sizeof (keystate
));
143 if (mods
& SHIFT_PRESSED
)
144 keystate
[VK_SHIFT
] = 0x80;
145 if (mods
& CAPSLOCK_ON
)
146 keystate
[VK_CAPITAL
] = 1;
147 if ((mods
& LEFT_CTRL_PRESSED
) && (mods
& RIGHT_ALT_PRESSED
))
149 keystate
[VK_CONTROL
] = 0x80;
150 keystate
[VK_LCONTROL
] = 0x80;
151 keystate
[VK_MENU
] = 0x80;
152 keystate
[VK_RMENU
] = 0x80;
155 isdead
= ToAscii (event
->wVirtualKeyCode
, event
->wVirtualScanCode
,
156 keystate
, (LPWORD
) ansi_code
, 0);
159 event
->uChar
.AsciiChar
= ansi_code
[0];
163 /* Map virtual key codes into:
166 Other - Map non-ASCII keys into X keysyms so that they are looked up
167 correctly in keyboard.c
169 Return, escape and tab are mapped to ASCII rather than coming back
170 as non-ASCII to be more compatible with old-style keyboard support. */
172 static int map_virt_key
[256] =
181 0x69, /* VK_CANCEL */
195 -1, -1, -1, -1, -1, -1,
207 0x60, /* VK_SELECT */
209 0x62, /* VK_EXECUTE */
210 -1, /* VK_SNAPSHOT */
211 0x63, /* VK_INSERT */
212 0xff, /* VK_DELETE */
214 -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, /* 0 - 9 */
215 -1, -1, -1, -1, -1, -1, -1,
216 -2, -2, -2, -2, -2, -2, -2, -2, /* A - Z */
217 -2, -2, -2, -2, -2, -2, -2, -2,
218 -2, -2, -2, -2, -2, -2, -2, -2,
221 0xb0, /* VK_NUMPAD0 */
222 0xb1, /* VK_NUMPAD1 */
223 0xb2, /* VK_NUMPAD2 */
224 0xb3, /* VK_NUMPAD3 */
225 0xb4, /* VK_NUMPAD4 */
226 0xb5, /* VK_NUMPAD5 */
227 0xb6, /* VK_NUMPAD6 */
228 0xb7, /* VK_NUMPAD7 */
229 0xb8, /* VK_NUMPAD8 */
230 0xb9, /* VK_NUMPAD9 */
231 0xaa, /* VK_MULTIPLY */
233 0xac, /* VK_SEPARATOR */
234 0xad, /* VK_SUBTRACT */
235 0xae, /* VK_DECIMAL */
236 0xaf, /* VK_DIVIDE */
261 -1, -1, -1, -1, -1, -1, -1, -1,
262 0x7f, /* VK_NUMLOCK */
263 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9f */
264 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xaf */
265 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb9 */
273 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xcf */
274 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xda */
275 -2, -2, -2, -2, -2, /* 0xdf */
280 -2, -2, -2, -2, -2, -2, -2, /* 0xef */
281 -2, -2, -2, -2, -2, -2,
282 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xff */
285 /* return code -1 means that event_queue_ptr won't be incremented.
286 In other word, this event makes two key codes. (by himi) */
288 key_event (KEY_EVENT_RECORD
*event
, struct input_event
*emacs_ev
)
292 static BOOL map_virt_key_init_done
;
294 /* Skip key-up events. */
295 if (!event
->bKeyDown
)
298 if (event
->wVirtualKeyCode
> 0xff)
300 printf ("Unknown key code %d\n", event
->wVirtualKeyCode
);
304 /* Patch needed for German keyboard. Ulrich Leodolter (1/11/95). */
305 if (! map_virt_key_init_done
)
309 if ((vk
= VkKeyScan (0x3c)) >= 0 && vk
< 256) map_virt_key
[vk
] = -2; /* less */
310 if ((vk
= VkKeyScan (0x3e)) >= 0 && vk
< 256) map_virt_key
[vk
] = -2; /* greater */
312 map_virt_key_init_done
= TRUE
;
315 /* BUGBUG - Ignores the repeat count
316 It's questionable whether we want to obey the repeat count anyway
317 since keys usually aren't repeated unless key events back up in
318 the queue. If they're backing up then we don't generally want
319 to honor them later since that leads to significant slop in
320 cursor motion when the system is under heavy load. */
322 map
= map_virt_key
[event
->wVirtualKeyCode
];
330 emacs_ev
->kind
= ascii_keystroke
;
331 key_flag
= win32_kbd_patch_key (event
); /* 95.7.25 by himi */
334 XSETINT (emacs_ev
->code
, event
->uChar
.AsciiChar
);
340 if ((event
->dwControlKeyState
& NLS_IME_CONVERSION
)
341 && !(event
->dwControlKeyState
& RIGHT_ALT_PRESSED
)
342 && !(event
->dwControlKeyState
& LEFT_ALT_PRESSED
)
343 && !(event
->dwControlKeyState
& RIGHT_CTRL_PRESSED
)
344 && !(event
->dwControlKeyState
& LEFT_CTRL_PRESSED
))
346 emacs_ev
->kind
= ascii_keystroke
;
347 XSETINT (emacs_ev
->code
, event
->uChar
.AsciiChar
);
356 emacs_ev
->kind
= non_ascii_keystroke
;
358 /* use Windows keysym map */
359 XSETINT (emacs_ev
->code
, event
->wVirtualKeyCode
);
362 * make_lispy_event () now requires non-ascii codes to have
363 * the full X keysym values (2nd byte is 0xff). add it on.
366 XSETINT (emacs_ev
->code
, map
);
367 #endif /* HAVE_NTGUI */
369 /* for Mule 2.2 (Based on Emacs 19.28) */
371 XSET (emacs_ev
->frame_or_window
, Lisp_Frame
, get_frame ());
373 XSETFRAME (emacs_ev
->frame_or_window
, get_frame ());
375 emacs_ev
->modifiers
= win32_kbd_mods_to_emacs (event
->dwControlKeyState
);
376 emacs_ev
->timestamp
= GetTickCount ();
377 if (key_flag
== 2) return -1; /* 95.7.25 by himi */
381 /* Mouse position hook. */
383 win32_mouse_position (FRAME_PTR
*f
,
387 Lisp_Object
*bar_window
,
388 enum scroll_bar_part
*part
,
402 selected_frame
->mouse_moved
= 0;
406 *time
= movement_time
;
411 /* Remember mouse motion and notify emacs. */
413 mouse_moved_to (int x
, int y
)
415 /* If we're in the same place, ignore it */
416 if (x
!= movement_pos
.X
|| y
!= movement_pos
.Y
)
418 selected_frame
->mouse_moved
= 1;
421 movement_time
= GetTickCount ();
425 /* Consoles return button bits in a strange order:
426 least significant - Leftmost button
427 next - Rightmost button
431 Assume emacs likes three button mice, so
435 Others increase from there. */
437 static int emacs_button_translation
[NUM_MOUSE_BUTTONS
] =
443 do_mouse_event (MOUSE_EVENT_RECORD
*event
,
444 struct input_event
*emacs_ev
)
446 static DWORD button_state
= 0;
447 DWORD but_change
, mask
;
450 if (event
->dwEventFlags
== MOUSE_MOVED
)
452 /* For movement events we just note that the mouse has moved
453 so that emacs will generate drag events. */
454 mouse_moved_to (event
->dwMousePosition
.X
, event
->dwMousePosition
.Y
);
458 /* It looks like the console code sends us a mouse event with
459 dwButtonState == 0 when a window is activated. Ignore this case. */
460 if (event
->dwButtonState
== button_state
)
463 emacs_ev
->kind
= mouse_click
;
465 /* Find out what button has changed state since the last button event. */
466 but_change
= button_state
^ event
->dwButtonState
;
468 for (i
= 0; i
< NUM_MOUSE_BUTTONS
; i
++, mask
<<= 1)
469 if (but_change
& mask
)
471 XSETINT (emacs_ev
->code
, emacs_button_translation
[i
]);
475 /* If the changed button is out of emacs' range (highly unlikely)
476 ignore this event. */
477 if (i
== NUM_MOUSE_BUTTONS
)
480 button_state
= event
->dwButtonState
;
481 emacs_ev
->timestamp
= GetTickCount ();
482 emacs_ev
->modifiers
= win32_kbd_mods_to_emacs (event
->dwControlKeyState
) |
483 ((event
->dwButtonState
& mask
) ? down_modifier
: up_modifier
);
485 XSETFASTINT (emacs_ev
->x
, event
->dwMousePosition
.X
);
486 XSETFASTINT (emacs_ev
->y
, event
->dwMousePosition
.Y
);
487 /* for Mule 2.2 (Based on Emacs 19.28 */
489 XSET (emacs_ev
->frame_or_window
, Lisp_Frame
, get_frame ());
491 XSETFRAME (emacs_ev
->frame_or_window
, get_frame ());
498 resize_event (WINDOW_BUFFER_SIZE_RECORD
*event
)
500 FRAME_PTR f
= get_frame ();
502 change_frame_size (f
, event
->dwSize
.Y
, event
->dwSize
.X
, 0, 1);
503 SET_FRAME_GARBAGED (f
);
507 win32_read_socket (int sd
, struct input_event
*bufp
, int numchars
,
508 int waitp
, int expected
)
510 BOOL no_events
= TRUE
;
511 int nev
, ret
= 0, add
;
513 if (interrupt_input_blocked
)
515 interrupt_input_pending
= 1;
519 interrupt_input_pending
= 0;
524 nev
= fill_queue (waitp
!= 0);
527 /* If nev == -1, there was some kind of error
528 If nev == 0 then waitp must be zero and no events were available
534 while (nev
> 0 && numchars
> 0)
536 switch (queue_ptr
->EventType
)
539 add
= key_event (&queue_ptr
->Event
.KeyEvent
, bufp
);
540 if (add
== -1) /* 95.7.25 by himi */
551 add
= do_mouse_event (&queue_ptr
->Event
.MouseEvent
, bufp
);
557 case WINDOW_BUFFER_SIZE_EVENT
:
558 resize_event (&queue_ptr
->Event
.WindowBufferSizeEvent
);
563 /* Internal event types, ignored. */
571 if (ret
> 0 || expected
== 0)