summaryrefslogtreecommitdiff
path: root/src/keyboard.c
diff options
context:
space:
mode:
authorChong Yidong <cyd@gnu.org>2012-02-24 16:34:09 +0800
committerChong Yidong <cyd@gnu.org>2012-02-24 16:34:09 +0800
commit9486df08b798f31960779d86c60cc341e606b864 (patch)
treec1eb77ae3b5d9c0cabcd23da3be59f07364cc231 /src/keyboard.c
parent4bb82fa8b7a8360d9877b63794eba778405e2962 (diff)
downloademacs-9486df08b798f31960779d86c60cc341e606b864.tar.gz
Process multiple X selection requests in process_special_events.
* src/keyboard.c (process_special_events): Handle all X selection requests in kbd_buffer, not just the next one. Fixes: debbugs:8869
Diffstat (limited to 'src/keyboard.c')
-rw-r--r--src/keyboard.c60
1 files changed, 42 insertions, 18 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index d4ff3c58f9b..f791773c352 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -4154,29 +4154,55 @@ kbd_buffer_get_event (KBOARD **kbp,
static void
process_special_events (void)
{
- while (kbd_fetch_ptr != kbd_store_ptr)
- {
- struct input_event *event;
+ struct input_event *event;
- event = ((kbd_fetch_ptr < kbd_buffer + KBD_BUFFER_SIZE)
- ? kbd_fetch_ptr
- : kbd_buffer);
-
- last_event_timestamp = event->timestamp;
+ for (event = kbd_fetch_ptr; event != kbd_store_ptr; ++event)
+ {
+ if (event == kbd_buffer + KBD_BUFFER_SIZE)
+ {
+ event = kbd_buffer;
+ if (event == kbd_store_ptr)
+ break;
+ }
- /* These two kinds of events get special handling
- and don't actually appear to the command loop. */
+ /* If we find a stored X selection request, handle it now. */
if (event->kind == SELECTION_REQUEST_EVENT
|| event->kind == SELECTION_CLEAR_EVENT)
{
#ifdef HAVE_X11
- struct input_event copy;
- /* Remove it from the buffer before processing it,
- since otherwise swallow_events called recursively could see it
- and process it again. */
- copy = *event;
- kbd_fetch_ptr = event + 1;
+ /* Remove the event from the fifo buffer before processing;
+ otherwise swallow_events called recursively could see it
+ and process it again. To do this, we move the events
+ between kbd_fetch_ptr and EVENT one slot to the right,
+ cyclically. */
+
+ struct input_event copy = *event;
+ struct input_event *beg
+ = (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE)
+ ? kbd_buffer : kbd_fetch_ptr;
+
+ if (event > beg)
+ memmove (beg + 1, beg, (event - beg) * sizeof (struct input_event));
+ else if (event < beg)
+ {
+ if (event > kbd_buffer)
+ memmove (kbd_buffer + 1, kbd_buffer,
+ (event - kbd_buffer) * sizeof (struct input_event));
+ *kbd_buffer = *(kbd_buffer + KBD_BUFFER_SIZE - 1);
+ if (beg < kbd_buffer + KBD_BUFFER_SIZE - 1)
+ memmove (beg + 1, beg,
+ (kbd_buffer + KBD_BUFFER_SIZE - 1 - beg)
+ * sizeof (struct input_event));
+ }
+
+ if (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE)
+ kbd_fetch_ptr = kbd_buffer + 1;
+ else
+ kbd_fetch_ptr++;
+
+ /* X wants last_event_timestamp for selection ownership. */
+ last_event_timestamp = copy.timestamp;
input_pending = readable_events (0);
x_handle_selection_event (&copy);
#else
@@ -4185,8 +4211,6 @@ process_special_events (void)
abort ();
#endif
}
- else
- break;
}
}