summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn <sabetts@juicebox>2008-02-06 14:16:37 -0800
committerShawn <sabetts@juicebox>2008-02-06 14:16:37 -0800
commitbd51b1705292845686f8f682d15f6b7b90ddc787 (patch)
tree17419004fb598453f019bc57cc1d33063a0f1327
parentcbcc8f2882ac8985a027b5c8423b5e764c51c158 (diff)
downloadratpoison-bd51b1705292845686f8f682d15f6b7b90ddc787.zip
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.
-rw-r--r--src/actions.c36
-rw-r--r--src/events.c2
-rw-r--r--src/input.c40
-rw-r--r--src/input.h2
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; i<frames; i++)
@@ -2966,17 +2964,21 @@ cmd_resize (int interactive, struct cmdarg **args)
unsigned int mod;
KeySym c;
struct list_head *bk;
+ Window focus;
+ int revert;
/* If we haven't got at least 2 frames, there isn't anything to
scale. */
if (num_frames (s) < 2)
return cmdret_new (RET_FAILURE, NULL);
- XGrabKeyboard (dpy, s->key_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);