X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/29a2c30ff67263ad887a15b2d6c728505ee656a0..974aae61bbb8c05e0d0fc1a95b419fe596423fd8:/src/w32inevt.c diff --git a/src/w32inevt.c b/src/w32inevt.c index f31f88edf0..cc7c5e1e61 100644 --- a/src/w32inevt.c +++ b/src/w32inevt.c @@ -15,21 +15,28 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. Drew Bliss 01-Oct-93 Adapted from ntkbd.c by Tim Fleehart */ -#include "config.h" +#ifdef HAVE_CONFIG_H +#include +#endif #include #include #include +#ifndef MOUSE_MOVED +#define MOUSE_MOVED 1 +#endif + #include "lisp.h" +#include "keyboard.h" #include "frame.h" #include "blockinput.h" #include "termhooks.h" @@ -49,6 +56,9 @@ extern void reinvoke_input_signal (void); /* from dispnew.c */ extern int change_frame_size (FRAME_PTR, int, int, int, int); +/* from w32console.c */ +extern int w32_use_full_screen_buffer; + /* from w32fns.c */ extern Lisp_Object Vw32_alt_is_meta; extern unsigned int map_keypad_keys (unsigned int, unsigned int); @@ -60,6 +70,7 @@ extern Lisp_Object Vw32_enable_num_lock; extern Lisp_Object Vw32_recognize_altgr; extern Lisp_Object Vw32_pass_lwindow_to_system; extern Lisp_Object Vw32_pass_rwindow_to_system; +extern Lisp_Object Vw32_phantom_key_code; extern Lisp_Object Vw32_lwindow_modifier; extern Lisp_Object Vw32_rwindow_modifier; extern Lisp_Object Vw32_apps_modifier; @@ -71,15 +82,15 @@ extern unsigned int w32_key_to_modifier (int key); static INPUT_RECORD event_queue[EVENT_QUEUE_SIZE]; static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue; -static int +static int fill_queue (BOOL block) { BOOL rc; DWORD events_waiting; - + if (queue_ptr < queue_end) return queue_end-queue_ptr; - + if (!block) { /* Check to see if there are some events to read before we try @@ -89,7 +100,7 @@ fill_queue (BOOL block) if (events_waiting == 0) return 0; } - + rc = ReadConsoleInput (keyboard_handle, event_queue, EVENT_QUEUE_SIZE, &events_waiting); if (!rc) @@ -103,13 +114,13 @@ fill_queue (BOOL block) and return the frame for it Right now, there's only one frame so return it. */ -static FRAME_PTR +static FRAME_PTR get_frame (void) { - return selected_frame; + return SELECTED_FRAME (); } -/* Translate console modifiers to emacs modifiers. +/* Translate console modifiers to emacs modifiers. German keyboard support (Kai Morgan Zeise 2/18/95). */ int w32_kbd_mods_to_emacs (DWORD mods, WORD key) @@ -118,18 +129,18 @@ w32_kbd_mods_to_emacs (DWORD mods, WORD key) /* If we recognize right-alt and left-ctrl as AltGr, and it has been pressed, first remove those modifiers. */ - if (!NILP (Vw32_recognize_altgr) - && (mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) + if (!NILP (Vw32_recognize_altgr) + && (mods & (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) mods &= ~ (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED); if (mods & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) retval = ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier); - + if (mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) { retval |= ctrl_modifier; - if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) + if ((mods & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) == (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) retval |= meta_modifier; } @@ -201,14 +212,14 @@ w32_kbd_patch_key (KEY_EVENT_RECORD *event) isdead = 0; return 1; } - if (event->uChar.AsciiChar != 0) + if (event->uChar.AsciiChar != 0) return 1; memset (keystate, 0, sizeof (keystate)); keystate[key_code] = 0x80; - if (mods & SHIFT_PRESSED) + if (mods & SHIFT_PRESSED) keystate[VK_SHIFT] = 0x80; - if (mods & CAPSLOCK_ON) + if (mods & CAPSLOCK_ON) keystate[VK_CAPITAL] = 1; /* If we recognize right-alt and left-ctrl as AltGr, set the key states accordingly before invoking ToAscii. */ @@ -261,7 +272,7 @@ w32_kbd_patch_key (KEY_EVENT_RECORD *event) keystate, (LPWORD) ansi_code, 0); } - if (isdead == 0) + if (isdead == 0) return 0; event->uChar.AsciiChar = ansi_code[0]; return isdead; @@ -270,12 +281,13 @@ w32_kbd_patch_key (KEY_EVENT_RECORD *event) extern char *lispy_function_keys[]; -/* return code -1 means that event_queue_ptr won't be incremented. +static int faked_key = 0; + +/* return code -1 means that event_queue_ptr won't be incremented. In other word, this event makes two key codes. (by himi) */ -int +int key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead) { - static int faked_key = 0; static int mod_key_state = 0; int wParam; @@ -317,8 +329,11 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead) Space which we will ignore. */ if ((mod_key_state & LEFT_WIN_PRESSED) == 0) { - faked_key = VK_SPACE; - keybd_event (VK_SPACE, (BYTE) MapVirtualKey (VK_SPACE, 0), 0, 0); + if (NUMBERP (Vw32_phantom_key_code)) + faked_key = XUINT (Vw32_phantom_key_code) & 255; + else + faked_key = VK_SPACE; + keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0); } } mod_key_state |= LEFT_WIN_PRESSED; @@ -330,8 +345,11 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead) { if ((mod_key_state & RIGHT_WIN_PRESSED) == 0) { - faked_key = VK_SPACE; - keybd_event (VK_SPACE, (BYTE) MapVirtualKey (VK_SPACE, 0), 0, 0); + if (NUMBERP (Vw32_phantom_key_code)) + faked_key = XUINT (Vw32_phantom_key_code) & 255; + else + faked_key = VK_SPACE; + keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0); } } mod_key_state |= RIGHT_WIN_PRESSED; @@ -379,6 +397,23 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead) case VK_CONTROL: case VK_SHIFT: return 0; + case VK_CANCEL: + /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL, + which is confusing for purposes of key binding; convert + VK_CANCEL events into VK_PAUSE events. */ + event->wVirtualKeyCode = VK_PAUSE; + break; + case VK_PAUSE: + /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing + for purposes of key binding; convert these back into + VK_NUMLOCK events, at least when we want to see NumLock key + presses. (Note that there is never any possibility that + VK_PAUSE with Ctrl really is C-Pause as per above.) */ + if (NILP (Vw32_enable_num_lock) + && (event->dwControlKeyState + & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0) + event->wVirtualKeyCode = VK_NUMLOCK; + break; } /* Recognize state of Windows and Apps keys. */ @@ -391,7 +426,7 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead) if (lispy_function_keys[event->wVirtualKeyCode] == 0) { - emacs_ev->kind = ascii_keystroke; + emacs_ev->kind = ASCII_KEYSTROKE_EVENT; if (!NILP (Vw32_recognize_altgr) && (event->dwControlKeyState & LEFT_CTRL_PRESSED) @@ -429,12 +464,12 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead) } if (event->uChar.AsciiChar == 0) return 0; - XSETINT (emacs_ev->code, event->uChar.AsciiChar); + emacs_ev->code = event->uChar.AsciiChar; } else { - emacs_ev->kind = non_ascii_keystroke; - XSETINT (emacs_ev->code, event->wVirtualKeyCode); + emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT; + emacs_ev->code = event->wVirtualKeyCode; } XSETFRAME (emacs_ev->frame_or_window, get_frame ()); @@ -444,12 +479,36 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead) return 1; } +int +w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state) +{ + int cur_state = (GetKeyState (vk_code) & 1); + + if (NILP (new_state) + || (NUMBERP (new_state) + && ((XUINT (new_state)) & 1) != cur_state)) + { + faked_key = vk_code; + + keybd_event ((BYTE) vk_code, + (BYTE) MapVirtualKey (vk_code, 0), + KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); + keybd_event ((BYTE) vk_code, + (BYTE) MapVirtualKey (vk_code, 0), + KEYEVENTF_EXTENDEDKEY | 0, 0); + keybd_event ((BYTE) vk_code, + (BYTE) MapVirtualKey (vk_code, 0), + KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); + cur_state = !cur_state; + } + + return cur_state; +} + /* Mouse position hook. */ -void +void w32_console_mouse_position (FRAME_PTR *f, -#ifndef MULE int insist, -#endif Lisp_Object *bar_window, enum scroll_bar_part *part, Lisp_Object *x, @@ -458,30 +517,28 @@ w32_console_mouse_position (FRAME_PTR *f, { BLOCK_INPUT; -#ifndef MULE insist = insist; -#endif *f = get_frame (); *bar_window = Qnil; *part = 0; - selected_frame->mouse_moved = 0; - - *x = movement_pos.X; - *y = movement_pos.Y; + SELECTED_FRAME ()->mouse_moved = 0; + + XSETINT(*x, movement_pos.X); + XSETINT(*y, movement_pos.Y); *time = movement_time; - + UNBLOCK_INPUT; } /* Remember mouse motion and notify emacs. */ -static void +static void mouse_moved_to (int x, int y) { /* If we're in the same place, ignore it */ if (x != movement_pos.X || y != movement_pos.Y) { - selected_frame->mouse_moved = 1; + SELECTED_FRAME ()->mouse_moved = 1; movement_pos.X = x; movement_pos.Y = y; movement_time = GetTickCount (); @@ -500,19 +557,20 @@ mouse_moved_to (int x, int y) Right == 2 Others increase from there. */ -static int emacs_button_translation[NUM_MOUSE_BUTTONS] = +#define NUM_TRANSLATED_MOUSE_BUTTONS 3 +static int emacs_button_translation[NUM_TRANSLATED_MOUSE_BUTTONS] = { - 0, 2, 1, 3, 4, + 0, 2, 1 }; -static int +static int do_mouse_event (MOUSE_EVENT_RECORD *event, struct input_event *emacs_ev) { static DWORD button_state = 0; DWORD but_change, mask; int i; - + if (event->dwEventFlags == MOUSE_MOVED) { /* For movement events we just note that the mouse has moved @@ -520,34 +578,32 @@ do_mouse_event (MOUSE_EVENT_RECORD *event, mouse_moved_to (event->dwMousePosition.X, event->dwMousePosition.Y); return 0; } - + /* It looks like the console code sends us a mouse event with dwButtonState == 0 when a window is activated. Ignore this case. */ if (event->dwButtonState == button_state) return 0; - - emacs_ev->kind = mouse_click; - + + emacs_ev->kind = MOUSE_CLICK_EVENT; + /* Find out what button has changed state since the last button event. */ but_change = button_state ^ event->dwButtonState; mask = 1; - for (i = 0; i < NUM_MOUSE_BUTTONS; i++, mask <<= 1) + for (i = 0; mask; i++, mask <<= 1) if (but_change & mask) { - XSETINT (emacs_ev->code, emacs_button_translation[i]); + if (i < NUM_TRANSLATED_MOUSE_BUTTONS) + emacs_ev->code = emacs_button_translation[i]; + else + emacs_ev->code = i; break; } - /* If the changed button is out of emacs' range (highly unlikely) - ignore this event. */ - if (i == NUM_MOUSE_BUTTONS) - return 0; - button_state = event->dwButtonState; emacs_ev->timestamp = GetTickCount (); emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, 0) | ((event->dwButtonState & mask) ? down_modifier : up_modifier); - + XSETFASTINT (emacs_ev->x, event->dwMousePosition.X); XSETFASTINT (emacs_ev->y, event->dwMousePosition.Y); /* for Mule 2.2 (Based on Emacs 19.28 */ @@ -556,22 +612,37 @@ do_mouse_event (MOUSE_EVENT_RECORD *event, #else XSETFRAME (emacs_ev->frame_or_window, get_frame ()); #endif - + return 1; } -static void +static void resize_event (WINDOW_BUFFER_SIZE_RECORD *event) { FRAME_PTR f = get_frame (); - + change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1); SET_FRAME_GARBAGED (f); } -int -w32_console_read_socket (int sd, struct input_event *bufp, int numchars, - int expected) +static void +maybe_generate_resize_event () +{ + CONSOLE_SCREEN_BUFFER_INFO info; + FRAME_PTR f = get_frame (); + + GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info); + + /* It is okay to call this unconditionally, since it will do nothing + if the size hasn't actually changed. */ + change_frame_size (f, + 1 + info.srWindow.Bottom - info.srWindow.Top, + 1 + info.srWindow.Right - info.srWindow.Left, + 0, 0); +} + +int +w32_console_read_socket (int sd, int expected, struct input_event *hold_quit) { BOOL no_events = TRUE; int nev, ret = 0, add; @@ -582,10 +653,10 @@ w32_console_read_socket (int sd, struct input_event *bufp, int numchars, interrupt_input_pending = 1; return -1; } - + interrupt_input_pending = 0; BLOCK_INPUT; - + for (;;) { nev = fill_queue (0); @@ -598,39 +669,44 @@ w32_console_read_socket (int sd, struct input_event *bufp, int numchars, return nev; } - while (nev > 0 && numchars > 0) + while (nev > 0) { + struct input_event inev; + + EVENT_INIT (inev); + inev.kind = NO_EVENT; + inev.arg = Qnil; + switch (queue_ptr->EventType) { case KEY_EVENT: - add = key_event (&queue_ptr->Event.KeyEvent, bufp, &isdead); + add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead); if (add == -1) /* 95.7.25 by himi */ - { + { queue_ptr--; add = 1; } - bufp += add; - ret += add; - numchars -= add; + if (add) + kbd_buffer_store_event_hold (&inev, hold_quit); break; case MOUSE_EVENT: - add = do_mouse_event (&queue_ptr->Event.MouseEvent, bufp); - bufp += add; - ret += add; - numchars -= add; + add = do_mouse_event (&queue_ptr->Event.MouseEvent, &inev); + if (add) + kbd_buffer_store_event_hold (&inev, hold_quit); break; case WINDOW_BUFFER_SIZE_EVENT: - resize_event (&queue_ptr->Event.WindowBufferSizeEvent); + if (w32_use_full_screen_buffer) + resize_event (&queue_ptr->Event.WindowBufferSizeEvent); break; - + case MENU_EVENT: case FOCUS_EVENT: /* Internal event types, ignored. */ break; } - + queue_ptr++; nev--; } @@ -638,7 +714,16 @@ w32_console_read_socket (int sd, struct input_event *bufp, int numchars, if (ret > 0 || expected == 0) break; } - + + /* We don't get told about changes in the window size (only the buffer + size, which we no longer care about), so we have to check it + periodically. */ + if (!w32_use_full_screen_buffer) + maybe_generate_resize_event (); + UNBLOCK_INPUT; return ret; } + +/* arch-tag: 0bcb39b7-d085-4b85-9070-6750e8c03047 + (do not change this comment) */