From bd51b1705292845686f8f682d15f6b7b90ddc787 Mon Sep 17 00:00:00 2001 From: Shawn Date: Wed, 6 Feb 2008 14:16:37 -0800 Subject: Change the way input is read Before rp used xgrabkeyboard to read a key. Instead, the keyboard is frozen when a top level key is read. Then when rp reads a key it first sets the input focus to a suitable location such as key_window or input_window, then thaws the keyboard and waits for a keypress. When a key is pressed the keyboard is frozen again and the process repeats until ratpoison is done reading input. At that point the keyboard is thawed in a way that future keystrokes do not refreeze the keyboard. --- src/actions.c | 36 ++++++++++++------------------------ src/events.c | 2 ++ src/input.c | 40 +++++++++++++++++++++++++++++++++++----- src/input.h | 2 ++ 4 files changed, 51 insertions(+), 29 deletions(-) diff --git a/src/actions.c b/src/actions.c index 0de31ed..6bf53d3 100644 --- a/src/actions.c +++ b/src/actions.c @@ -1739,9 +1739,7 @@ read_frame (struct argspec *spec, struct sbuf *s, struct cmdarg **arg) XSync (dpy, False); /* Read a key. */ - XGrabKeyboard (dpy, current_screen()->key_window, False, GrabModeSync, GrabModeAsync, CurrentTime); - read_key (&c, &mod, keysym_buf, keysym_bufsize); - XUngrabKeyboard (dpy, CurrentTime); + read_single_key (&c, &mod, keysym_buf, keysym_bufsize); /* Destroy our number windows and free the array. */ for (i=0; ikey_window, False, GrabModeSync, GrabModeAsync, CurrentTime); - /* Save the frameset in case the user aborts. */ bk = screen_copy_frameset (s); + /* Get ready to read keys. */ + XGetInputFocus (dpy, &focus, &revert); + set_window_focus (s->key_window); + while (1) { struct resize_binding *binding; @@ -3025,7 +3027,7 @@ cmd_resize (int interactive, struct cmdarg **args) free (bk); hide_frame_indicator (); - XUngrabKeyboard (dpy, CurrentTime); + set_window_focus (focus); } else { @@ -3144,7 +3146,6 @@ cmdret * cmd_license (int interactive, struct cmdarg **args) { rp_screen *s = current_screen(); - XEvent ev; int x = 10; int y = 10; int i; @@ -3181,7 +3182,6 @@ cmd_license (int interactive, struct cmdarg **args) XInstallColormap (dpy, s->def_cmap); XMapRaised (dpy, s->help_window); - XGrabKeyboard (dpy, s->help_window, False, GrabModeSync, GrabModeAsync, CurrentTime); /* Find the longest line. */ for(i=0; license_text[i]; i++) @@ -3210,10 +3210,7 @@ cmd_license (int interactive, struct cmdarg **args) } /* Wait for a key press. */ - XMaskEvent (dpy, KeyPressMask, &ev); - - /* Revert focus. */ - XUngrabKeyboard (dpy, CurrentTime); + read_any_key (); XUnmapWindow (dpy, s->help_window); /* Possibly restore colormap. */ @@ -3243,7 +3240,6 @@ cmd_help (int interactive, struct cmdarg **args) if (interactive) { rp_screen *s = current_screen(); - XEvent ev; int i, old_i; int x = 10; int y = 0; @@ -3257,7 +3253,6 @@ cmd_help (int interactive, struct cmdarg **args) XInstallColormap (dpy, s->def_cmap); XMapRaised (dpy, s->help_window); - XGrabKeyboard (dpy, s->help_window, False, GrabModeSync, GrabModeAsync, CurrentTime); XmbDrawString (dpy, s->help_window, defaults.font, s->normal_gc, 10, y + rp_font_ascent, @@ -3342,8 +3337,7 @@ cmd_help (int interactive, struct cmdarg **args) } } - XMaskEvent (dpy, KeyPressMask, &ev); - XUngrabKeyboard (dpy, CurrentTime); + read_any_key(); XUnmapWindow (dpy, s->help_window); /* Possibly restore colormap. */ @@ -4953,8 +4947,6 @@ cmd_readkey (int interactive, struct cmdarg **args) map = ARG(0,keymap); - XGrabKeyboard (dpy, current_screen()->key_window, False, GrabModeSync, GrabModeAsync, CurrentTime); - /* Change the mouse icon to indicate to the user we are waiting for more keystrokes */ if (defaults.wait_for_key_cursor) @@ -4963,8 +4955,7 @@ cmd_readkey (int interactive, struct cmdarg **args) rat_grabbed = 1; } - read_key (&keysym, &mod, NULL, 0); - XUngrabKeyboard (dpy, CurrentTime); + read_single_key (&keysym, &mod, NULL, 0); if (rat_grabbed) ungrab_rat(); @@ -5506,8 +5497,6 @@ cmd_describekey (int interactive, struct cmdarg **args) map = ARG(0,keymap); - XGrabKeyboard (dpy, current_screen()->key_window, False, GrabModeSync, GrabModeAsync, CurrentTime); - /* Change the mouse icon to indicate to the user we are waiting for more keystrokes */ if (defaults.wait_for_key_cursor) @@ -5516,8 +5505,7 @@ cmd_describekey (int interactive, struct cmdarg **args) rat_grabbed = 1; } - read_key (&keysym, &mod, NULL, 0); - XUngrabKeyboard (dpy, CurrentTime); + read_single_key (&keysym, &mod, NULL, 0); if (rat_grabbed) ungrab_rat(); diff --git a/src/events.c b/src/events.c index bdc288f..ec26ceb 100644 --- a/src/events.c +++ b/src/events.c @@ -427,6 +427,8 @@ handle_key (KeySym ks, unsigned int mod, rp_screen *s) { PRINT_DEBUG(("Impossible: No matching key")); } + + /* All keys have been read so now we let the keyboard go. */ XAllowEvents (dpy, AsyncKeyboard, CurrentTime); } diff --git a/src/input.c b/src/input.c index 3350341..3297ac7 100644 --- a/src/input.c +++ b/src/input.c @@ -377,6 +377,30 @@ cook_keycode (XKeyEvent *ev, KeySym *keysym, unsigned int *mod, char *keysym_nam return nbytes; } +/* Wait for a key and discard it. */ +void +read_any_key () +{ + char buffer[513]; + unsigned int mod; + KeySym c; + + read_single_key (&c, &mod, buffer, sizeof (buffer)); +} + +/* The same as read_key, but handle focusing the key_window and reverting focus. */ +int +read_single_key (KeySym *keysym, unsigned int *modifiers, char *keysym_name, int len) +{ + Window focus; + int revert; + + XGetInputFocus (dpy, &focus, &revert); + set_window_focus (current_screen()->key_window); + read_key (keysym, modifiers, keysym_name, len); + set_window_focus (focus); +} + int read_key (KeySym *keysym, unsigned int *modifiers, char *keysym_name, int len) { @@ -386,10 +410,13 @@ read_key (KeySym *keysym, unsigned int *modifiers, char *keysym_name, int len) /* Read a key from the keyboard. */ do { - XMaskEvent (dpy, KeyPressMask, &ev); + /* The keyboard is frozen, so unfreeze it and allow another key to come in. */ + XAllowEvents (dpy, SyncKeyboard, CurrentTime); + + XMaskEvent (dpy, KeyPressMask|KeyRelease, &ev); *modifiers = ev.xkey.state; nbytes = cook_keycode (&ev.xkey, keysym, modifiers, keysym_name, len, 0); - } while (IsModifierKey (*keysym)); + } while (IsModifierKey (*keysym) || ev.xkey.type == KeyRelease); return nbytes; } @@ -503,6 +530,8 @@ get_more_input (char *prompt, char *preinput, rp_input_line *line; char *final_input; edit_status status; + Window focus; + int revert; #ifdef HAVE_HISTORY history_reset(); @@ -522,12 +551,13 @@ get_more_input (char *prompt, char *preinput, XMapWindow (dpy, s->input_window); XRaiseWindow (dpy, s->input_window); XClearWindow (dpy, s->input_window); + /* Switch focus to our input window to read the next key events. */ + XGetInputFocus (dpy, &focus, &revert); + set_window_focus (s->input_window); XSync (dpy, False); update_input_window (s, line); - XGrabKeyboard (dpy, s->input_window, False, GrabModeSync, GrabModeAsync, CurrentTime); - for (;;) { nbytes = read_key (&ch, &modifier, keysym_buf, keysym_bufsize); @@ -566,7 +596,7 @@ get_more_input (char *prompt, char *preinput, input_line_free (line); /* Revert focus. */ - XUngrabKeyboard (dpy, CurrentTime); + set_window_focus (focus); XUnmapWindow (dpy, s->input_window); /* Possibly restore colormap. */ diff --git a/src/input.h b/src/input.h index f3da6bc..676c6e7 100644 --- a/src/input.h +++ b/src/input.h @@ -26,6 +26,8 @@ char *keysym_to_string (KeySym keysym, unsigned int modifier); int cook_keycode (XKeyEvent *ev, KeySym *keysym, unsigned int *mod, char *keysym_name, int len, int ignore_bad_mods); char *get_input (char *prompt, completion_fn fn); char *get_more_input (char *prompt, char *preinput, completion_fn fn); +void read_any_key (); +int read_single_key (KeySym *keysym, unsigned int *modifiers, char *keysym_name, int len); int read_key (KeySym *keysym, unsigned int *modifiers, char *keysym_name, int len); unsigned int x11_mask_to_rp_mask (unsigned int mask); unsigned int rp_mask_to_x11_mask (unsigned int mask); -- cgit v1.2.3