1 /* Input event support for Windows NT port of GNU Emacs.
2 Copyright (C) 1992, 1993 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 /* Indicate mouse motion, from keyboard.c */
40 extern int mouse_moved
;
42 /* Info for last mouse motion */
43 static COORD movement_pos
;
44 static DWORD movement_time
;
47 extern void reinvoke_input_signal (void);
50 extern int change_frame_size (FRAME_PTR
, int, int, int, int);
53 #define EVENT_QUEUE_SIZE 50
54 static INPUT_RECORD event_queue
[EVENT_QUEUE_SIZE
];
55 static INPUT_RECORD
*queue_ptr
= event_queue
, *queue_end
= event_queue
;
58 fill_queue (BOOL block
)
63 if (queue_ptr
< queue_end
)
64 return queue_end
-queue_ptr
;
68 /* Check to see if there are some events to read before we try
69 because we can't block. */
70 if (!GetNumberOfConsoleInputEvents (keyboard_handle
, &events_waiting
))
72 if (events_waiting
== 0)
76 rc
= ReadConsoleInput (keyboard_handle
, event_queue
, EVENT_QUEUE_SIZE
,
80 queue_ptr
= event_queue
;
81 queue_end
= event_queue
+ events_waiting
;
82 return (int) events_waiting
;
85 /* In a generic, multi-frame world this should take a console handle
86 and return the frame for it
88 Right now, there's only one frame so return it. */
92 return selected_frame
;
96 #define SET_FRAME(o, f) XSETFRAME (o, f)
98 #define SET_FRAME(o, f) ((o) = Qnil)
101 /* Translate console modifiers to emacs modifiers. */
103 nt_kbd_mods_to_emacs (DWORD mods
)
105 return ((mods
& (RIGHT_ALT_PRESSED
| LEFT_ALT_PRESSED
)) ?
107 ((mods
& (RIGHT_CTRL_PRESSED
| LEFT_CTRL_PRESSED
)) ?
109 ((mods
& (SHIFT_PRESSED
| CAPSLOCK_ON
)) ?
113 /* Map virtual key codes into:
116 Other - Map non-ASCII keys into X keysyms so that they are looked up
117 correctly in keyboard.c
119 Return, escape and tab are mapped to ASCII rather than coming back
120 as non-ASCII to be more compatible with old-style keyboard support. */
122 static int map_virt_key
[256] =
127 0x69, /* VK_CANCEL */
141 -1, -1, -1, -1, -1, -1,
153 0x60, /* VK_SELECT */
155 0x62, /* VK_EXECUTE */
156 -1, /* VK_SNAPSHOT */
157 0x63, /* VK_INSERT */
158 0xff, /* VK_DELETE */
160 -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, /* 0 - 9 */
161 -1, -1, -1, -1, -1, -1, -1,
162 -2, -2, -2, -2, -2, -2, -2, -2, /* A - Z */
163 -2, -2, -2, -2, -2, -2, -2, -2,
164 -2, -2, -2, -2, -2, -2, -2, -2,
167 0xb0, /* VK_NUMPAD0 */
168 0xb1, /* VK_NUMPAD1 */
169 0xb2, /* VK_NUMPAD2 */
170 0xb3, /* VK_NUMPAD3 */
171 0xb4, /* VK_NUMPAD4 */
172 0xb5, /* VK_NUMPAD5 */
173 0xb6, /* VK_NUMPAD6 */
174 0xb7, /* VK_NUMPAD7 */
175 0xb8, /* VK_NUMPAD8 */
176 0xb9, /* VK_NUMPAD9 */
177 0xaa, /* VK_MULTIPLY */
179 0xac, /* VK_SEPARATOR */
180 0xad, /* VK_SUBTRACT */
181 0xae, /* VK_DECIMAL */
182 0xaf, /* VK_DIVIDE */
207 -1, -1, -1, -1, -1, -1, -1, -1,
208 0x7f, /* VK_NUMLOCK */
209 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x9f */
210 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xaf */
211 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xb9 */
219 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xcf */
220 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xda */
226 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0xef */
227 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* 0xff */
231 key_event (KEY_EVENT_RECORD
*event
, struct input_event
*emacs_ev
)
235 /* Skip key-up events. */
236 if (event
->bKeyDown
== FALSE
)
239 if (event
->wVirtualKeyCode
> 0xff)
241 printf ("Unknown key code %d\n", event
->wVirtualKeyCode
);
245 /* BUGBUG - Ignores the repeat count
246 It's questionable whether we want to obey the repeat count anyway
247 since keys usually aren't repeated unless key events back up in
248 the queue. If they're backing up then we don't generally want
249 to honor them later since that leads to significant slop in
250 cursor motion when the system is under heavy load. */
252 map
= map_virt_key
[event
->wVirtualKeyCode
];
260 emacs_ev
->kind
= ascii_keystroke
;
261 XSETINT (emacs_ev
->code
, event
->uChar
.AsciiChar
);
266 emacs_ev
->kind
= non_ascii_keystroke
;
268 * make_lispy_event () now requires non-ascii codes to have
269 * the full X keysym values (2nd byte is 0xff). add it on.
272 XSETINT (emacs_ev
->code
, map
);
274 SET_FRAME (emacs_ev
->frame_or_window
, get_frame ());
275 emacs_ev
->modifiers
= nt_kbd_mods_to_emacs (event
->dwControlKeyState
);
276 emacs_ev
->timestamp
= GetTickCount ();
280 /* Mouse position hook. */
282 win32_mouse_position (FRAME_PTR
*f
,
283 Lisp_Object
*bar_window
,
284 enum scroll_bar_part
*part
,
298 *time
= movement_time
;
303 /* Remember mouse motion and notify emacs. */
305 mouse_moved_to (int x
, int y
)
307 /* If we're in the same place, ignore it */
308 if (x
!= movement_pos
.X
|| y
!= movement_pos
.Y
)
313 movement_time
= GetTickCount ();
317 /* Consoles return button bits in a strange order:
318 least significant - Leftmost button
319 next - Rightmost button
323 Assume emacs likes three button mice, so
327 Others increase from there. */
329 static int emacs_button_translation
[NUM_MOUSE_BUTTONS
] =
335 do_mouse_event (MOUSE_EVENT_RECORD
*event
,
336 struct input_event
*emacs_ev
)
338 static DWORD button_state
= 0;
339 DWORD but_change
, mask
;
342 if (event
->dwEventFlags
== MOUSE_MOVED
)
344 /* For movement events we just note that the mouse has moved
345 so that emacs will generate drag events. */
346 mouse_moved_to (event
->dwMousePosition
.X
, event
->dwMousePosition
.Y
);
350 /* It looks like the console code sends us a mouse event with
351 dwButtonState == 0 when a window is activated. Ignore this case. */
352 if (event
->dwButtonState
== button_state
)
355 emacs_ev
->kind
= mouse_click
;
357 /* Find out what button has changed state since the last button event. */
358 but_change
= button_state
^ event
->dwButtonState
;
360 for (i
= 0; i
< NUM_MOUSE_BUTTONS
; i
++, mask
<<= 1)
361 if (but_change
& mask
)
363 XSETINT (emacs_ev
->code
, emacs_button_translation
[i
]);
367 /* If the changed button is out of emacs' range (highly unlikely)
368 ignore this event. */
369 if (i
== NUM_MOUSE_BUTTONS
)
372 button_state
= event
->dwButtonState
;
373 emacs_ev
->timestamp
= GetTickCount ();
374 emacs_ev
->modifiers
= nt_kbd_mods_to_emacs (event
->dwControlKeyState
) |
375 ((event
->dwButtonState
& mask
) ? down_modifier
: up_modifier
);
377 XSETFASTINT (emacs_ev
->x
, event
->dwMousePosition
.X
);
378 XSETFASTINT (emacs_ev
->y
, event
->dwMousePosition
.Y
);
379 SET_FRAME (emacs_ev
->frame_or_window
, get_frame ());
385 resize_event (WINDOW_BUFFER_SIZE_RECORD
*event
)
387 FRAME_PTR f
= get_frame ();
389 change_frame_size (f
, event
->dwSize
.Y
, event
->dwSize
.X
, 0, 1);
390 SET_FRAME_GARBAGED (f
);
394 win32_read_socket (int sd
, struct input_event
*bufp
, int numchars
,
395 int waitp
, int expected
)
397 BOOL no_events
= TRUE
;
398 int nev
, ret
= 0, add
;
400 if (interrupt_input_blocked
)
402 interrupt_input_pending
= 1;
406 interrupt_input_pending
= 0;
411 nev
= fill_queue (waitp
!= 0);
414 /* If nev == -1, there was some kind of error
415 If nev == 0 then waitp must be zero and no events were available
421 while (nev
> 0 && numchars
> 0)
423 switch (queue_ptr
->EventType
)
426 add
= key_event (&queue_ptr
->Event
.KeyEvent
, bufp
);
433 add
= do_mouse_event (&queue_ptr
->Event
.MouseEvent
, bufp
);
439 case WINDOW_BUFFER_SIZE_EVENT
:
440 resize_event (&queue_ptr
->Event
.WindowBufferSizeEvent
);
445 /* Internal event types, ignored. */
453 if (ret
> 0 || expected
== 0)