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 it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any later
11 GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 You should have received a copy of the GNU General Public License along
17 with GNU Emacs; see the file COPYING. If not, write to the Free Software
18 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21 Adapted from ntkbd.c by Tim Fleehart
33 #include "blockinput.h"
34 #include "termhooks.h"
36 /* stdin, from ntterm */
37 extern HANDLE keyboard_handle
;
39 /* Info for last mouse motion */
40 static COORD movement_pos
;
41 static DWORD movement_time
;
44 extern void reinvoke_input_signal (void);
47 extern int change_frame_size (FRAME_PTR
, int, int, int, int);
50 #define EVENT_QUEUE_SIZE 50
51 static INPUT_RECORD event_queue
[EVENT_QUEUE_SIZE
];
52 static INPUT_RECORD
*queue_ptr
= event_queue
, *queue_end
= event_queue
;
55 fill_queue (BOOL block
)
60 if (queue_ptr
< queue_end
)
61 return queue_end
-queue_ptr
;
65 /* Check to see if there are some events to read before we try
66 because we can't block. */
67 if (!GetNumberOfConsoleInputEvents (keyboard_handle
, &events_waiting
))
69 if (events_waiting
== 0)
73 rc
= ReadConsoleInput (keyboard_handle
, event_queue
, EVENT_QUEUE_SIZE
,
77 queue_ptr
= event_queue
;
78 queue_end
= event_queue
+ events_waiting
;
79 return (int) events_waiting
;
82 /* In a generic, multi-frame world this should take a console handle
83 and return the frame for it
85 Right now, there's only one frame so return it. */
89 return selected_frame
;
92 /* Translate console modifiers to emacs modifiers.
93 German keyboard support (Kai Morgan Zeise 2/18/95). */
95 win32_kbd_mods_to_emacs (DWORD mods
)
99 /* If AltGr has been pressed, remove it. */
100 if ((mods
& (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
))
101 == (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
))
102 mods
&= ~ (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
);
104 if (mods
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
105 retval
= meta_modifier
;
107 if (mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
109 retval
|= ctrl_modifier
;
110 if ((mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
111 == (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
112 retval
|= meta_modifier
;
115 if (((mods
& (SHIFT_PRESSED
| CAPSLOCK_ON
)) == SHIFT_PRESSED
)
116 || ((mods
& (SHIFT_PRESSED
| CAPSLOCK_ON
)) == CAPSLOCK_ON
))
117 retval
|= shift_modifier
;
122 /* Patch up NT keyboard events when info is missing that should be there,
123 assuming that map_virt_key says that the key is a valid ASCII char. */
124 static char win32_number_shift_map
[] = {
125 ')', '!', '@', '#', '$', '%', '^', '&', '*', '('
128 #define WIN32_KEY_SHIFTED(mods, no, yes) \
129 ((mods & (SHIFT_PRESSED | CAPSLOCK_ON)) ? yes : no)
132 win32_kbd_patch_key (KEY_EVENT_RECORD
*event
)
134 unsigned int key_code
= event
->wVirtualKeyCode
;
135 unsigned int mods
= event
->dwControlKeyState
;
136 int mapped_punct
= 0;
138 /* map_virt_key says its a valid key, but the uChar.AsciiChar field
139 is empty. patch up the uChar.AsciiChar field using wVirtualKeyCode. */
140 if (event
->uChar
.AsciiChar
== 0
141 && ((key_code
>= '0' && key_code
<= '9')
142 || (key_code
>= 'A' && key_code
<= 'Z')
143 || (key_code
>= 0xBA && key_code
<= 0xC0)
144 || (key_code
>= 0xDB && key_code
<= 0xDE)
146 if (key_code
>= '0' && key_code
<= '9') {
147 event
->uChar
.AsciiChar
=
148 WIN32_KEY_SHIFTED (mods
, key_code
,
149 win32_number_shift_map
[key_code
- '0']);
153 case 0xBA: mapped_punct
= WIN32_KEY_SHIFTED (mods
, ';', ':'); break;
154 case 0xBB: mapped_punct
= WIN32_KEY_SHIFTED (mods
, '=', '+'); break;
155 case 0xBC: mapped_punct
= WIN32_KEY_SHIFTED (mods
, ',', '<'); break;
156 case 0xBD: mapped_punct
= WIN32_KEY_SHIFTED (mods
, '-', '_'); break;
157 case 0xBE: mapped_punct
= WIN32_KEY_SHIFTED (mods
, '.', '>'); break;
158 case 0xBF: mapped_punct
= WIN32_KEY_SHIFTED (mods
, '/', '?'); break;
159 case 0xC0: mapped_punct
= WIN32_KEY_SHIFTED (mods
, '`', '~'); break;
160 case 0xDB: mapped_punct
= WIN32_KEY_SHIFTED (mods
, '[', '{'); break;
161 case 0xDC: mapped_punct
= WIN32_KEY_SHIFTED (mods
, '\\', '|'); break;
162 case 0xDD: mapped_punct
= WIN32_KEY_SHIFTED (mods
, ']', '}'); break;
163 case 0xDE: mapped_punct
= WIN32_KEY_SHIFTED (mods
, '\'', '"'); break;
169 event
->uChar
.AsciiChar
= mapped_punct
;
172 /* otherwise, it's a letter. */
173 event
->uChar
.AsciiChar
= WIN32_KEY_SHIFTED (mods
, key_code
- 'A' + 'a',
178 /* Map virtual key codes into:
181 Other - Map non-ASCII keys into X keysyms so that they are looked up
182 correctly in keyboard.c
184 Return, escape and tab are mapped to ASCII rather than coming back
185 as non-ASCII to be more compatible with old-style keyboard support. */
187 static int map_virt_key
[256] =
192 0x69, /* VK_CANCEL */
206 -1, -1, -1, -1, -1, -1,
218 0x60, /* VK_SELECT */
220 0x62, /* VK_EXECUTE */
221 -1, /* VK_SNAPSHOT */
222 0x63, /* VK_INSERT */
223 0xff, /* VK_DELETE */
225 -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, /* 0 - 9 */
226 -1, -1, -1, -1, -1, -1, -1,
227 -2, -2, -2, -2, -2, -2, -2, -2, /* A - Z */
228 -2, -2, -2, -2, -2, -2, -2, -2,
229 -2, -2, -2, -2, -2, -2, -2, -2,
232 0xb0, /* VK_NUMPAD0 */
233 0xb1, /* VK_NUMPAD1 */
234 0xb2, /* VK_NUMPAD2 */
235 0xb3, /* VK_NUMPAD3 */
236 0xb4, /* VK_NUMPAD4 */
237 0xb5, /* VK_NUMPAD5 */
238 0xb6, /* VK_NUMPAD6 */
239 0xb7, /* VK_NUMPAD7 */
240 0xb8, /* VK_NUMPAD8 */
241 0xb9, /* VK_NUMPAD9 */
242 0xaa, /* VK_MULTIPLY */
244 0xac, /* VK_SEPARATOR */
245 0xad, /* VK_SUBTRACT */
246 0xae, /* VK_DECIMAL */
247 0xaf, /* VK_DIVIDE */
272 -1, -1, -1, -1, -1, -1, -1, -1,
273 0x7f, /* VK_NUMLOCK */
274 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9f */
275 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xaf */
276 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb9 */
284 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xcf */
285 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xda */
286 -2, -2, -2, -2, -2, /* 0xdf */
291 -2, -2, -2, -2, -2, -2, -2, /* 0xef */
292 -2, -2, -2, -2, -2, -2,
293 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xff */
297 key_event (KEY_EVENT_RECORD
*event
, struct input_event
*emacs_ev
)
300 static BOOL map_virt_key_init_done
;
302 /* Skip key-up events. */
303 if (event
->bKeyDown
== FALSE
)
306 if (event
->wVirtualKeyCode
> 0xff)
308 printf ("Unknown key code %d\n", event
->wVirtualKeyCode
);
312 /* Patch needed for German keyboard. Ulrich Leodolter (1/11/95). */
313 if (! map_virt_key_init_done
)
317 if ((vk
= VkKeyScan (0x3c)) >= 0 && vk
< 256) map_virt_key
[vk
] = -2; /* less */
318 if ((vk
= VkKeyScan (0x3e)) >= 0 && vk
< 256) map_virt_key
[vk
] = -2; /* greater */
320 map_virt_key_init_done
= TRUE
;
323 /* BUGBUG - Ignores the repeat count
324 It's questionable whether we want to obey the repeat count anyway
325 since keys usually aren't repeated unless key events back up in
326 the queue. If they're backing up then we don't generally want
327 to honor them later since that leads to significant slop in
328 cursor motion when the system is under heavy load. */
330 map
= map_virt_key
[event
->wVirtualKeyCode
];
338 emacs_ev
->kind
= ascii_keystroke
;
339 win32_kbd_patch_key (event
);
340 XSETINT (emacs_ev
->code
, event
->uChar
.AsciiChar
);
345 emacs_ev
->kind
= non_ascii_keystroke
;
347 * make_lispy_event () now requires non-ascii codes to have
348 * the full X keysym values (2nd byte is 0xff). add it on.
351 XSETINT (emacs_ev
->code
, map
);
353 XSETFRAME (emacs_ev
->frame_or_window
, get_frame ());
354 emacs_ev
->modifiers
= win32_kbd_mods_to_emacs (event
->dwControlKeyState
);
355 emacs_ev
->timestamp
= GetTickCount ();
359 /* Mouse position hook. */
361 win32_mouse_position (FRAME_PTR
*f
,
363 Lisp_Object
*bar_window
,
364 enum scroll_bar_part
*part
,
376 selected_frame
->mouse_moved
= 0;
380 *time
= movement_time
;
385 /* Remember mouse motion and notify emacs. */
387 mouse_moved_to (int x
, int y
)
389 /* If we're in the same place, ignore it */
390 if (x
!= movement_pos
.X
|| y
!= movement_pos
.Y
)
392 selected_frame
->mouse_moved
= 1;
395 movement_time
= GetTickCount ();
399 /* Consoles return button bits in a strange order:
400 least significant - Leftmost button
401 next - Rightmost button
405 Assume emacs likes three button mice, so
409 Others increase from there. */
411 static int emacs_button_translation
[NUM_MOUSE_BUTTONS
] =
417 do_mouse_event (MOUSE_EVENT_RECORD
*event
,
418 struct input_event
*emacs_ev
)
420 static DWORD button_state
= 0;
421 DWORD but_change
, mask
;
424 if (event
->dwEventFlags
== MOUSE_MOVED
)
426 /* For movement events we just note that the mouse has moved
427 so that emacs will generate drag events. */
428 mouse_moved_to (event
->dwMousePosition
.X
, event
->dwMousePosition
.Y
);
432 /* It looks like the console code sends us a mouse event with
433 dwButtonState == 0 when a window is activated. Ignore this case. */
434 if (event
->dwButtonState
== button_state
)
437 emacs_ev
->kind
= mouse_click
;
439 /* Find out what button has changed state since the last button event. */
440 but_change
= button_state
^ event
->dwButtonState
;
442 for (i
= 0; i
< NUM_MOUSE_BUTTONS
; i
++, mask
<<= 1)
443 if (but_change
& mask
)
445 XSETINT (emacs_ev
->code
, emacs_button_translation
[i
]);
449 /* If the changed button is out of emacs' range (highly unlikely)
450 ignore this event. */
451 if (i
== NUM_MOUSE_BUTTONS
)
454 button_state
= event
->dwButtonState
;
455 emacs_ev
->timestamp
= GetTickCount ();
456 emacs_ev
->modifiers
= win32_kbd_mods_to_emacs (event
->dwControlKeyState
) |
457 ((event
->dwButtonState
& mask
) ? down_modifier
: up_modifier
);
459 XSETFASTINT (emacs_ev
->x
, event
->dwMousePosition
.X
);
460 XSETFASTINT (emacs_ev
->y
, event
->dwMousePosition
.Y
);
461 XSETFRAME (emacs_ev
->frame_or_window
, get_frame ());
467 resize_event (WINDOW_BUFFER_SIZE_RECORD
*event
)
469 FRAME_PTR f
= get_frame ();
471 change_frame_size (f
, event
->dwSize
.Y
, event
->dwSize
.X
, 0, 1);
472 SET_FRAME_GARBAGED (f
);
476 win32_read_socket (int sd
, struct input_event
*bufp
, int numchars
,
477 int waitp
, int expected
)
479 BOOL no_events
= TRUE
;
480 int nev
, ret
= 0, add
;
482 if (interrupt_input_blocked
)
484 interrupt_input_pending
= 1;
488 interrupt_input_pending
= 0;
493 nev
= fill_queue (waitp
!= 0);
496 /* If nev == -1, there was some kind of error
497 If nev == 0 then waitp must be zero and no events were available
503 while (nev
> 0 && numchars
> 0)
505 switch (queue_ptr
->EventType
)
508 add
= key_event (&queue_ptr
->Event
.KeyEvent
, bufp
);
515 add
= do_mouse_event (&queue_ptr
->Event
.MouseEvent
, bufp
);
521 case WINDOW_BUFFER_SIZE_EVENT
:
522 resize_event (&queue_ptr
->Event
.WindowBufferSizeEvent
);
527 /* Internal event types, ignored. */
535 if (ret
> 0 || expected
== 0)