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 extern Lisp_Object Vwin32_alt_is_meta
;
54 #define EVENT_QUEUE_SIZE 50
55 static INPUT_RECORD event_queue
[EVENT_QUEUE_SIZE
];
56 static INPUT_RECORD
*queue_ptr
= event_queue
, *queue_end
= event_queue
;
59 fill_queue (BOOL block
)
64 if (queue_ptr
< queue_end
)
65 return queue_end
-queue_ptr
;
69 /* Check to see if there are some events to read before we try
70 because we can't block. */
71 if (!GetNumberOfConsoleInputEvents (keyboard_handle
, &events_waiting
))
73 if (events_waiting
== 0)
77 rc
= ReadConsoleInput (keyboard_handle
, event_queue
, EVENT_QUEUE_SIZE
,
81 queue_ptr
= event_queue
;
82 queue_end
= event_queue
+ events_waiting
;
83 return (int) events_waiting
;
86 /* In a generic, multi-frame world this should take a console handle
87 and return the frame for it
89 Right now, there's only one frame so return it. */
93 return selected_frame
;
96 /* Translate console modifiers to emacs modifiers.
97 German keyboard support (Kai Morgan Zeise 2/18/95). */
99 win32_kbd_mods_to_emacs (DWORD mods
)
103 /* If AltGr has been pressed, remove it. */
104 if ((mods
& (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
))
105 == (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
))
106 mods
&= ~ (RIGHT_ALT_PRESSED
| LEFT_CTRL_PRESSED
);
108 if (mods
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
))
109 retval
= ((NILP (Vwin32_alt_is_meta
)) ? alt_modifier
: meta_modifier
);
111 if (mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
113 retval
|= ctrl_modifier
;
114 if ((mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
115 == (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
))
116 retval
|= meta_modifier
;
119 if (((mods
& (SHIFT_PRESSED
| CAPSLOCK_ON
)) == SHIFT_PRESSED
)
120 || ((mods
& (SHIFT_PRESSED
| CAPSLOCK_ON
)) == CAPSLOCK_ON
))
121 retval
|= shift_modifier
;
126 /* The return code indicates key code size. */
128 win32_kbd_patch_key (KEY_EVENT_RECORD
*event
)
130 unsigned int key_code
= event
->wVirtualKeyCode
;
131 unsigned int mods
= event
->dwControlKeyState
;
133 static BYTE ansi_code
[4];
134 static int isdead
= 0;
138 event
->uChar
.AsciiChar
= ansi_code
[2];
142 if (event
->uChar
.AsciiChar
!= 0)
145 memset (keystate
, 0, sizeof (keystate
));
146 if (mods
& SHIFT_PRESSED
)
147 keystate
[VK_SHIFT
] = 0x80;
148 if (mods
& CAPSLOCK_ON
)
149 keystate
[VK_CAPITAL
] = 1;
150 if ((mods
& LEFT_CTRL_PRESSED
) && (mods
& RIGHT_ALT_PRESSED
))
152 keystate
[VK_CONTROL
] = 0x80;
153 keystate
[VK_LCONTROL
] = 0x80;
154 keystate
[VK_MENU
] = 0x80;
155 keystate
[VK_RMENU
] = 0x80;
158 isdead
= ToAscii (event
->wVirtualKeyCode
, event
->wVirtualScanCode
,
159 keystate
, (LPWORD
) ansi_code
, 0);
162 event
->uChar
.AsciiChar
= ansi_code
[0];
166 /* Map virtual key codes into:
169 Other - Map non-ASCII keys into X keysyms so that they are looked up
170 correctly in keyboard.c
172 Return, escape and tab are mapped to ASCII rather than coming back
173 as non-ASCII to be more compatible with old-style keyboard support. */
175 static int map_virt_key
[256] =
184 0x69, /* VK_CANCEL */
198 -1, -1, -1, -1, -1, -1,
210 0x60, /* VK_SELECT */
212 0x62, /* VK_EXECUTE */
213 -1, /* VK_SNAPSHOT */
214 0x63, /* VK_INSERT */
215 0xff, /* VK_DELETE */
217 -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, /* 0 - 9 */
218 -1, -1, -1, -1, -1, -1, -1,
219 -2, -2, -2, -2, -2, -2, -2, -2, /* A - Z */
220 -2, -2, -2, -2, -2, -2, -2, -2,
221 -2, -2, -2, -2, -2, -2, -2, -2,
224 0xb0, /* VK_NUMPAD0 */
225 0xb1, /* VK_NUMPAD1 */
226 0xb2, /* VK_NUMPAD2 */
227 0xb3, /* VK_NUMPAD3 */
228 0xb4, /* VK_NUMPAD4 */
229 0xb5, /* VK_NUMPAD5 */
230 0xb6, /* VK_NUMPAD6 */
231 0xb7, /* VK_NUMPAD7 */
232 0xb8, /* VK_NUMPAD8 */
233 0xb9, /* VK_NUMPAD9 */
234 0xaa, /* VK_MULTIPLY */
236 0xac, /* VK_SEPARATOR */
237 0xad, /* VK_SUBTRACT */
238 0xae, /* VK_DECIMAL */
239 0xaf, /* VK_DIVIDE */
264 -1, -1, -1, -1, -1, -1, -1, -1,
265 0x7f, /* VK_NUMLOCK */
266 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9f */
267 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xaf */
268 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb9 */
276 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xcf */
277 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xda */
278 -2, -2, -2, -2, -2, /* 0xdf */
283 -2, -2, -2, -2, -2, -2, -2, /* 0xef */
284 -2, -2, -2, -2, -2, -2,
285 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xff */
288 /* return code -1 means that event_queue_ptr won't be incremented.
289 In other word, this event makes two key codes. (by himi) */
291 key_event (KEY_EVENT_RECORD
*event
, struct input_event
*emacs_ev
)
295 static BOOL map_virt_key_init_done
;
297 /* Skip key-up events. */
298 if (!event
->bKeyDown
)
301 if (event
->wVirtualKeyCode
> 0xff)
303 printf ("Unknown key code %d\n", event
->wVirtualKeyCode
);
307 /* Patch needed for German keyboard. Ulrich Leodolter (1/11/95). */
308 if (! map_virt_key_init_done
)
312 if ((vk
= VkKeyScan (0x3c)) >= 0 && vk
< 256) map_virt_key
[vk
] = -2; /* less */
313 if ((vk
= VkKeyScan (0x3e)) >= 0 && vk
< 256) map_virt_key
[vk
] = -2; /* greater */
315 map_virt_key_init_done
= TRUE
;
318 /* BUGBUG - Ignores the repeat count
319 It's questionable whether we want to obey the repeat count anyway
320 since keys usually aren't repeated unless key events back up in
321 the queue. If they're backing up then we don't generally want
322 to honor them later since that leads to significant slop in
323 cursor motion when the system is under heavy load. */
325 map
= map_virt_key
[event
->wVirtualKeyCode
];
333 emacs_ev
->kind
= ascii_keystroke
;
334 key_flag
= win32_kbd_patch_key (event
); /* 95.7.25 by himi */
337 XSETINT (emacs_ev
->code
, event
->uChar
.AsciiChar
);
343 if ((event
->dwControlKeyState
& NLS_IME_CONVERSION
)
344 && !(event
->dwControlKeyState
& RIGHT_ALT_PRESSED
)
345 && !(event
->dwControlKeyState
& LEFT_ALT_PRESSED
)
346 && !(event
->dwControlKeyState
& RIGHT_CTRL_PRESSED
)
347 && !(event
->dwControlKeyState
& LEFT_CTRL_PRESSED
))
349 emacs_ev
->kind
= ascii_keystroke
;
350 XSETINT (emacs_ev
->code
, event
->uChar
.AsciiChar
);
359 emacs_ev
->kind
= non_ascii_keystroke
;
361 /* use Windows keysym map */
362 XSETINT (emacs_ev
->code
, event
->wVirtualKeyCode
);
365 * make_lispy_event () now requires non-ascii codes to have
366 * the full X keysym values (2nd byte is 0xff). add it on.
369 XSETINT (emacs_ev
->code
, map
);
370 #endif /* HAVE_NTGUI */
372 /* for Mule 2.2 (Based on Emacs 19.28) */
374 XSET (emacs_ev
->frame_or_window
, Lisp_Frame
, get_frame ());
376 XSETFRAME (emacs_ev
->frame_or_window
, get_frame ());
378 emacs_ev
->modifiers
= win32_kbd_mods_to_emacs (event
->dwControlKeyState
);
379 emacs_ev
->timestamp
= GetTickCount ();
380 if (key_flag
== 2) return -1; /* 95.7.25 by himi */
384 /* Mouse position hook. */
386 win32_mouse_position (FRAME_PTR
*f
,
390 Lisp_Object
*bar_window
,
391 enum scroll_bar_part
*part
,
405 selected_frame
->mouse_moved
= 0;
409 *time
= movement_time
;
414 /* Remember mouse motion and notify emacs. */
416 mouse_moved_to (int x
, int y
)
418 /* If we're in the same place, ignore it */
419 if (x
!= movement_pos
.X
|| y
!= movement_pos
.Y
)
421 selected_frame
->mouse_moved
= 1;
424 movement_time
= GetTickCount ();
428 /* Consoles return button bits in a strange order:
429 least significant - Leftmost button
430 next - Rightmost button
434 Assume emacs likes three button mice, so
438 Others increase from there. */
440 static int emacs_button_translation
[NUM_MOUSE_BUTTONS
] =
446 do_mouse_event (MOUSE_EVENT_RECORD
*event
,
447 struct input_event
*emacs_ev
)
449 static DWORD button_state
= 0;
450 DWORD but_change
, mask
;
453 if (event
->dwEventFlags
== MOUSE_MOVED
)
455 /* For movement events we just note that the mouse has moved
456 so that emacs will generate drag events. */
457 mouse_moved_to (event
->dwMousePosition
.X
, event
->dwMousePosition
.Y
);
461 /* It looks like the console code sends us a mouse event with
462 dwButtonState == 0 when a window is activated. Ignore this case. */
463 if (event
->dwButtonState
== button_state
)
466 emacs_ev
->kind
= mouse_click
;
468 /* Find out what button has changed state since the last button event. */
469 but_change
= button_state
^ event
->dwButtonState
;
471 for (i
= 0; i
< NUM_MOUSE_BUTTONS
; i
++, mask
<<= 1)
472 if (but_change
& mask
)
474 XSETINT (emacs_ev
->code
, emacs_button_translation
[i
]);
478 /* If the changed button is out of emacs' range (highly unlikely)
479 ignore this event. */
480 if (i
== NUM_MOUSE_BUTTONS
)
483 button_state
= event
->dwButtonState
;
484 emacs_ev
->timestamp
= GetTickCount ();
485 emacs_ev
->modifiers
= win32_kbd_mods_to_emacs (event
->dwControlKeyState
) |
486 ((event
->dwButtonState
& mask
) ? down_modifier
: up_modifier
);
488 XSETFASTINT (emacs_ev
->x
, event
->dwMousePosition
.X
);
489 XSETFASTINT (emacs_ev
->y
, event
->dwMousePosition
.Y
);
490 /* for Mule 2.2 (Based on Emacs 19.28 */
492 XSET (emacs_ev
->frame_or_window
, Lisp_Frame
, get_frame ());
494 XSETFRAME (emacs_ev
->frame_or_window
, get_frame ());
501 resize_event (WINDOW_BUFFER_SIZE_RECORD
*event
)
503 FRAME_PTR f
= get_frame ();
505 change_frame_size (f
, event
->dwSize
.Y
, event
->dwSize
.X
, 0, 1);
506 SET_FRAME_GARBAGED (f
);
510 win32_read_socket (int sd
, struct input_event
*bufp
, int numchars
,
511 int waitp
, int expected
)
513 BOOL no_events
= TRUE
;
514 int nev
, ret
= 0, add
;
516 if (interrupt_input_blocked
)
518 interrupt_input_pending
= 1;
522 interrupt_input_pending
= 0;
527 nev
= fill_queue (0);
530 /* If nev == -1, there was some kind of error
531 If nev == 0 then waitp must be zero and no events were available
537 while (nev
> 0 && numchars
> 0)
539 switch (queue_ptr
->EventType
)
542 add
= key_event (&queue_ptr
->Event
.KeyEvent
, bufp
);
543 if (add
== -1) /* 95.7.25 by himi */
554 add
= do_mouse_event (&queue_ptr
->Event
.MouseEvent
, bufp
);
560 case WINDOW_BUFFER_SIZE_EVENT
:
561 resize_event (&queue_ptr
->Event
.WindowBufferSizeEvent
);
566 /* Internal event types, ignored. */
574 if (ret
> 0 || expected
== 0)