Subject: Re: bug#76559: 31.0.50; [-O3 + PGTK] Crash when 'copying as kill'/'killing word'

From: Paul Eggert <[email-masked]>
Date: Mon, 3 Mar 2025 00:02:13 -0800

On 2025-03-01 21:10, Po Lu wrote:
> It doesn't take control flow into account, but rather _every statement
> operand_ in the current procedure that addresses an aggregate declared
> in the same procedure.

Although, as you mentioned, we could work around this wrong-code GCC bug 
by using -fno-tree-sra (something we already do for GCC pre-SSE2 x86), 
we should avoid the tricky union locals that trigger the bug on x86-64 
with gcc -flto. After all, these union locals make the code harder for 
humans to read, so removing them is a win regardless of the GCC bug. And 
if removing the union locals happens to work around the GCC bug then so 
much the better.

Proposed patch attached.

From 73a04276f9ccb53a6002f37393a0673b463fc014 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Sun, 2 Mar 2025 22:07:08 -0800
Subject: [PATCH] Avoid some union buffered_input_event uses

Simplify by using separate local vars for struct input_event and
struct selection_input_event, rather than a single local var that
is the union of the two.  This makes the code easier to follow by
the human reader, and should help avoid GCC bug 117423
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117423> and
therefore work around Emacs bug 76559 <https://bugs.gnu.org/76559>.
* src/androidterm.c (handle_one_android_event):
* src/gtkutil.c (xg_widget_key_press_event_cb):
* src/pgtkterm.c (evq_flush):
* src/xterm.c (handle_one_xevent): Use struct input_event and
kbd_buffer_store_event_hold, or struct selection_input_event and
kbd_buffer_store_selection_event_hold, rather than union
buffered_input_event and union buffered_input_event.
* src/keyboard.c (beware_long_paste, maybe_quit_while_no_input):
New functions, broken out from kbd_buffer_store_buffered_event.
(kbd_buffer_store_event_hold): Define here, with a simplified
version of the body of the old kbd_buffer_store_buffered_event,
rather than defining in keyboard.h.  Specialize to struct
input_event.  First arg is now pointer-to-const, for clarity.
(kbd_buffer_store_selection_event_hold): New function; it is
a simplified version of the old kbd_buffer_store_buffered_event,
specialized to struct selection_input_event and with a first
arg now pointer-to-const for clarity.
(is_ignored_event_kind): Accept enum event_kind instead of
union buffered_input_event.  All callers changed.
* src/keyboard.h (kbd_buffer_store_event_hold):
Remove definition, as keyboard.c now defines it.
* src/pgtkterm.c (evq_grow_if_needed): New function.
(evq_enqueue, evq_selection_enqueue): Two functions now,
not one.  Args are now struct input_event const * or
struct selection_input_event const *, not
union buffered_input_event *.  All callers changed.
This lets us simplify the callers so that they need
not use the union.
---
 src/androidterm.c | 171 +++++++-------
 src/gtkutil.c     |  42 ++--
 src/keyboard.c    | 105 ++++++---
 src/keyboard.h    |  15 +-
 src/pgtkterm.c    | 582 ++++++++++++++++++++++++----------------------
 src/xterm.c       | 402 ++++++++++++++++----------------
 6 files changed, 687 insertions(+), 630 deletions(-)

diff --git a/src/androidterm.c b/src/androidterm.c
index 3cb9eab3606..79ee374f2ca 100644
--- a/src/androidterm.c
+++ b/src/androidterm.c
@@ -827,7 +827,7 @@ handle_one_android_event (struct android_display_info *dpyinfo,
   union android_event configureEvent;
   struct frame *f, *any, *mouse_frame;
   Mouse_HLInfo *hlinfo;
-  union buffered_input_event inev;
+  struct input_event inev;
   int modifiers, count, do_help;
   struct android_touch_point *touchpoint, **last;
   Lisp_Object window;
@@ -851,7 +851,7 @@ handle_one_android_event (struct android_display_info *dpyinfo,
   if (any && any->wait_event_type == event->type)
     any->wait_event_type = 0; /* Indicates we got it.  */
 
-  EVENT_INIT (inev.ie);
+  EVENT_INIT (inev);
 
   switch (event->type)
     {
@@ -922,8 +922,8 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 	if (!FRAME_TOOLTIP_P (f)
 	    && (old_left != f->left_pos || old_top != f->top_pos))
 	  {
-	    inev.ie.kind = MOVE_FRAME_EVENT;
-	    XSETFRAME (inev.ie.frame_or_window, f);
+	    inev.kind = MOVE_FRAME_EVENT;
+	    XSETFRAME (inev.frame_or_window, f);
 	  }
 
 	if (f && FRAME_OUTPUT_DATA (f)->need_cursor_updates)
@@ -982,10 +982,10 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 	memset (&compose_status, 0, sizeof (compose_status));
 
       /* Common for all keysym input events.  */
-      XSETFRAME (inev.ie.frame_or_window, any);
-      inev.ie.modifiers
+      XSETFRAME (inev.frame_or_window, any);
+      inev.modifiers
 	= android_android_to_emacs_modifiers (dpyinfo, modifiers);
-      inev.ie.timestamp = event->xkey.time;
+      inev.timestamp = event->xkey.time;
 
       keysym = event->xkey.keycode;
 
@@ -1019,8 +1019,8 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 
 	if (event->xkey.keycode == (uint32_t) -1)
 	  {
-	    inev.ie.kind = PREEDIT_TEXT_EVENT;
-	    inev.ie.arg = Qnil;
+	    inev.kind = PREEDIT_TEXT_EVENT;
+	    inev.arg = Qnil;
 
 	    /* If text was looked up, decode it and make it the
 	       preedit text.  */
@@ -1028,7 +1028,7 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 	    if (status_return == ANDROID_LOOKUP_CHARS && nchars)
 	      {
 		copy_bufptr[nchars] = 0;
-		inev.ie.arg = from_unicode_buffer (copy_bufptr);
+		inev.arg = from_unicode_buffer (copy_bufptr);
 	      }
 
 	    goto done_keysym;
@@ -1047,11 +1047,11 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 	  /* Deal with characters.  */
 
 	  if (copy_bufptr[0] < 128)
-	    inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+	    inev.kind = ASCII_KEYSTROKE_EVENT;
 	  else
-	    inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+	    inev.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
 
-	  inev.ie.code = copy_bufptr[0];
+	  inev.code = copy_bufptr[0];
 	}
       else if (nchars < 2 && keysym)
 	{
@@ -1061,8 +1061,8 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 
 	  /* Next, deal with special ``characters'' by giving the
 	     keycode to keyboard.c.  */
-	  inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
-	  inev.ie.code = keysym;
+	  inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+	  inev.code = keysym;
 	}
       else
 	{
@@ -1070,25 +1070,25 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 
 	  for (i = 0; i < nchars; ++i)
 	    {
-	      inev.ie.kind = (SINGLE_BYTE_CHAR_P (copy_bufptr[i])
-			      ? ASCII_KEYSTROKE_EVENT
-			      : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-	      inev.ie.code = copy_bufptr[i];
+	      inev.kind = (SINGLE_BYTE_CHAR_P (copy_bufptr[i])
+			   ? ASCII_KEYSTROKE_EVENT
+			   : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+	      inev.code = copy_bufptr[i];
 
 	      /* If the character is actually '\n', then change this
 		 to RET.  */
 
 	      if (copy_bufptr[i] == '\n')
 		{
-		  inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
-		  inev.ie.code = 66;
+		  inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+		  inev.code = 66;
 		}
 
-	      kbd_buffer_store_buffered_event (&inev, hold_quit);
+	      kbd_buffer_store_event_hold (&inev, hold_quit);
 	    }
 
 	  count += nchars;
-	  inev.ie.kind = NO_EVENT;  /* Already stored above.  */
+	  inev.kind = NO_EVENT;  /* Already stored above.  */
 	}
 
       goto done_keysym;
@@ -1108,7 +1108,7 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 
     case ANDROID_FOCUS_IN:
     case ANDROID_FOCUS_OUT:
-      android_detect_focus_change (dpyinfo, any, event, &inev.ie);
+      android_detect_focus_change (dpyinfo, any, event, &inev);
       goto OTHER;
 
     case ANDROID_WINDOW_ACTION:
@@ -1136,8 +1136,8 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 	      if (!f)
 		goto OTHER;
 
-	      inev.ie.kind = DELETE_WINDOW_EVENT;
-	      XSETFRAME (inev.ie.frame_or_window, f);
+	      inev.kind = DELETE_WINDOW_EVENT;
+	      XSETFRAME (inev.frame_or_window, f);
 	    }
 	}
 
@@ -1196,8 +1196,8 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 		  && !EQ (window, last_mouse_window)
 		  && !EQ (window, selected_window))
 		{
-		  inev.ie.kind = SELECT_WINDOW_EVENT;
-		  inev.ie.frame_or_window = window;
+		  inev.kind = SELECT_WINDOW_EVENT;
+		  inev.frame_or_window = window;
 		}
 
 	      /* Remember the last window where we saw the mouse.  */
@@ -1378,10 +1378,10 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 	  if (!(tab_bar_p && NILP (tab_bar_arg)) && !tool_bar_p)
 	    if (! popup_activated ())
 	      {
-		android_construct_mouse_click (&inev.ie, &event->xbutton, f);
+		android_construct_mouse_click (&inev, &event->xbutton, f);
 
 		if (!NILP (tab_bar_arg))
-		  inev.ie.arg = tab_bar_arg;
+		  inev.arg = tab_bar_arg;
 	      }
 	}
 
@@ -1424,8 +1424,8 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 	  /* Simply update the tool position and send an update.  */
 	  touchpoint->x = event->touch.x;
 	  touchpoint->y = event->touch.y;
-	  android_update_tools (any, &inev.ie);
-	  inev.ie.timestamp = event->touch.time;
+	  android_update_tools (any, &inev);
+	  inev.timestamp = event->touch.time;
 
 	  goto OTHER;
 	}
@@ -1498,12 +1498,12 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 	}
 
       /* Now generate the Emacs event.  */
-      inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT;
-      inev.ie.timestamp = event->touch.time;
-      XSETFRAME (inev.ie.frame_or_window, any);
-      XSETINT (inev.ie.x, event->touch.x);
-      XSETINT (inev.ie.y, event->touch.y);
-      XSETINT (inev.ie.arg, event->touch.pointer_id);
+      inev.kind = TOUCHSCREEN_BEGIN_EVENT;
+      inev.timestamp = event->touch.time;
+      XSETFRAME (inev.frame_or_window, any);
+      XSETINT (inev.x, event->touch.x);
+      XSETINT (inev.y, event->touch.y);
+      XSETINT (inev.arg, event->touch.pointer_id);
 
       goto OTHER;
 
@@ -1526,8 +1526,8 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 
       touchpoint->x = event->touch.x;
       touchpoint->y = event->touch.y;
-      android_update_tools (any, &inev.ie);
-      inev.ie.timestamp = event->touch.time;
+      android_update_tools (any, &inev);
+      inev.timestamp = event->touch.time;
 
       goto OTHER;
 
@@ -1569,18 +1569,18 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 		 grabbed by the tool bar).  */
 	      xfree (touchpoint);
 
-	      inev.ie.kind = TOUCHSCREEN_END_EVENT;
-	      inev.ie.timestamp = event->touch.time;
+	      inev.kind = TOUCHSCREEN_END_EVENT;
+	      inev.timestamp = event->touch.time;
 
 	      /* Report whether the sequence has been canceled.  */
 
 	      if (event->touch.flags & ANDROID_TOUCH_SEQUENCE_CANCELED)
-		inev.ie.modifiers = 1;
+		inev.modifiers = 1;
 
-	      XSETFRAME (inev.ie.frame_or_window, any);
-	      XSETINT (inev.ie.x, event->touch.x);
-	      XSETINT (inev.ie.y, event->touch.y);
-	      XSETINT (inev.ie.arg, event->touch.pointer_id);
+	      XSETFRAME (inev.frame_or_window, any);
+	      XSETINT (inev.x, event->touch.x);
+	      XSETINT (inev.y, event->touch.y);
+	      XSETINT (inev.arg, event->touch.pointer_id);
 
 	      /* Break out of the loop.  */
 	      goto OTHER;
@@ -1629,24 +1629,24 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 	    }
 
 	  /* Determine what kind of event to send.  */
-	  inev.ie.kind = ((fabs (wheel_event_y)
+	  inev.kind = ((fabs (wheel_event_y)
 			   >= fabs (wheel_event_x))
 			  ? WHEEL_EVENT : HORIZ_WHEEL_EVENT);
-	  inev.ie.timestamp = event->wheel.time;
+	  inev.timestamp = event->wheel.time;
 
 	  /* Set the event coordinates.  */
-	  XSETINT (inev.ie.x, event->wheel.x);
-	  XSETINT (inev.ie.y, event->wheel.y);
+	  XSETINT (inev.x, event->wheel.x);
+	  XSETINT (inev.y, event->wheel.y);
 
 	  /* Set the frame.  */
-	  XSETFRAME (inev.ie.frame_or_window, any);
+	  XSETFRAME (inev.frame_or_window, any);
 
 	  /* Figure out the scroll direction.  */
-	  inev.ie.modifiers = (signbit ((fabs (wheel_event_x)
-					 >= fabs (wheel_event_y))
-					? wheel_event_x
-					: wheel_event_y)
-			       ? down_modifier : up_modifier);
+	  inev.modifiers = (signbit ((fabs (wheel_event_x)
+				      >= fabs (wheel_event_y))
+				     ? wheel_event_x
+				     : wheel_event_y)
+			    ? down_modifier : up_modifier);
 
 	  /* Figure out how much to scale the deltas by.  */
 	  window = window_from_coordinates (any, event->wheel.x,
@@ -1664,16 +1664,14 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 	  scroll_unit = pow (scroll_height, 2.0 / 3.0);
 
 	  /* Add the keyboard modifiers.  */
-	  inev.ie.modifiers
+	  inev.modifiers
 	    |= android_android_to_emacs_modifiers (dpyinfo,
 						   event->wheel.state);
 
 	  /* Finally include the scroll deltas.  */
-	  inev.ie.arg = list3 (Qnil,
-			       make_float (wheel_event_x
-					   * scroll_unit),
-			       make_float (wheel_event_y
-					   * scroll_unit));
+	  inev.arg = list3 (Qnil,
+			    make_float (wheel_event_x * scroll_unit),
+			    make_float (wheel_event_y * scroll_unit));
 
 	  wheel_event_x = 0.0;
 	  wheel_event_y = 0.0;
@@ -1693,8 +1691,8 @@ handle_one_android_event (struct android_display_info *dpyinfo,
       SET_FRAME_VISIBLE (any, false);
       SET_FRAME_ICONIFIED (any, true);
 
-      inev.ie.kind = ICONIFY_EVENT;
-      XSETFRAME (inev.ie.frame_or_window, any);
+      inev.kind = ICONIFY_EVENT;
+      XSETFRAME (inev.frame_or_window, any);
       goto OTHER;
 
     case ANDROID_DEICONIFIED:
@@ -1708,8 +1706,8 @@ handle_one_android_event (struct android_display_info *dpyinfo,
       SET_FRAME_VISIBLE (any, true);
       SET_FRAME_ICONIFIED (any, false);
 
-      inev.ie.kind = DEICONIFY_EVENT;
-      XSETFRAME (inev.ie.frame_or_window, any);
+      inev.kind = DEICONIFY_EVENT;
+      XSETFRAME (inev.frame_or_window, any);
       goto OTHER;
 
       /* Context menu handling.  */
@@ -1757,12 +1755,12 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 	goto OTHER;
 
       /* Generate a drag and drop event to convey its position.  */
-      inev.ie.kind = DRAG_N_DROP_EVENT;
-      XSETFRAME (inev.ie.frame_or_window, any);
-      inev.ie.timestamp = ANDROID_CURRENT_TIME;
-      XSETINT (inev.ie.x, event->dnd.x);
-      XSETINT (inev.ie.y, event->dnd.y);
-      inev.ie.arg = Fcons (inev.ie.x, inev.ie.y);
+      inev.kind = DRAG_N_DROP_EVENT;
+      XSETFRAME (inev.frame_or_window, any);
+      inev.timestamp = ANDROID_CURRENT_TIME;
+      XSETINT (inev.x, event->dnd.x);
+      XSETINT (inev.y, event->dnd.y);
+      inev.arg = Fcons (inev.x, inev.y);
       goto OTHER;
 
     case ANDROID_DND_URI_EVENT:
@@ -1778,15 +1776,15 @@ handle_one_android_event (struct android_display_info *dpyinfo,
 	 content or file URI or a string to be inserted.  Generate an
 	 event with this information.  */
 
-      inev.ie.kind = DRAG_N_DROP_EVENT;
-      XSETFRAME (inev.ie.frame_or_window, any);
-      inev.ie.timestamp = ANDROID_CURRENT_TIME;
-      XSETINT (inev.ie.x, event->dnd.x);
-      XSETINT (inev.ie.y, event->dnd.y);
-      inev.ie.arg = Fcons ((event->type == ANDROID_DND_TEXT_EVENT
-			    ? Qtext : Quri),
-			   android_decode_utf16 (event->dnd.uri_or_string,
-						 event->dnd.length));
+      inev.kind = DRAG_N_DROP_EVENT;
+      XSETFRAME (inev.frame_or_window, any);
+      inev.timestamp = ANDROID_CURRENT_TIME;
+      XSETINT (inev.x, event->dnd.x);
+      XSETINT (inev.y, event->dnd.y);
+      inev.arg = Fcons ((event->type == ANDROID_DND_TEXT_EVENT
+			 ? Qtext : Quri),
+			android_decode_utf16 (event->dnd.uri_or_string,
+					      event->dnd.length));
       free (event->dnd.uri_or_string);
       goto OTHER;
 
@@ -1794,15 +1792,14 @@ handle_one_android_event (struct android_display_info *dpyinfo,
     case ANDROID_NOTIFICATION_ACTION:
 
       if (event->notification.type == ANDROID_NOTIFICATION_DELETED)
-	android_notification_deleted (&event->notification, &inev.ie);
+	android_notification_deleted (&event->notification, &inev);
       else
 	{
 	  Lisp_Object action;
 
 	  action = android_decode_utf16 (event->notification.action,
 					 event->notification.length);
-	  android_notification_action (&event->notification, &inev.ie,
-				       action);
+	  android_notification_action (&event->notification, &inev, action);
 	}
 
       /* Free dynamically allocated data.  */
@@ -1815,9 +1812,9 @@ handle_one_android_event (struct android_display_info *dpyinfo,
     }
 
  OTHER:
-  if (inev.ie.kind != NO_EVENT)
+  if (inev.kind != NO_EVENT)
     {
-      kbd_buffer_store_buffered_event (&inev, hold_quit);
+      kbd_buffer_store_event_hold (&inev, hold_quit);
       count++;
     }
 
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 0770874eb40..164531aaeb3 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -6382,7 +6382,7 @@ xg_widget_key_press_event_cb (GtkWidget *widget, GdkEvent *event,
 {
   Lisp_Object tail, tem;
   struct frame *f = NULL;
-  union buffered_input_event inev;
+  struct input_event inev;
   guint keysym = event->key.keyval;
   unsigned int xstate;
   gunichar uc;
@@ -6419,15 +6419,15 @@ xg_widget_key_press_event_cb (GtkWidget *widget, GdkEvent *event,
       && !FRAME_DISPLAY_INFO (f)->prefer_native_input)
     return true;
 
-  EVENT_INIT (inev.ie);
-  XSETFRAME (inev.ie.frame_or_window, f);
+  EVENT_INIT (inev);
+  XSETFRAME (inev.frame_or_window, f);
 
   xstate = xg_virtual_mods_to_x (FRAME_DISPLAY_INFO (f),
 				 event->key.state);
 
-  inev.ie.modifiers
+  inev.modifiers
     |= x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), xstate);
-  inev.ie.timestamp = event->key.time;
+  inev.timestamp = event->key.time;
 
 #ifdef HAVE_XINPUT2
   if (event->key.time == pending_keystroke_time)
@@ -6436,7 +6436,7 @@ xg_widget_key_press_event_cb (GtkWidget *widget, GdkEvent *event,
 				  FRAME_DISPLAY_INFO (f)->pending_keystroke_source);
 
       if (source)
-	inev.ie.device = source->name;
+	inev.device = source->name;
     }
 #endif
 
@@ -6455,8 +6455,8 @@ xg_widget_key_press_event_cb (GtkWidget *widget, GdkEvent *event,
   if (keysym >= 32 && keysym < 128)
     /* Avoid explicitly decoding each ASCII character.  */
     {
-      inev.ie.kind = ASCII_KEYSTROKE_EVENT;
-      inev.ie.code = keysym;
+      inev.kind = ASCII_KEYSTROKE_EVENT;
+      inev.code = keysym;
       goto done;
     }
 
@@ -6464,10 +6464,10 @@ xg_widget_key_press_event_cb (GtkWidget *widget, GdkEvent *event,
   if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
     {
       if (keysym < 0x01000080)
-	inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+	inev.kind = ASCII_KEYSTROKE_EVENT;
       else
-	inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
-      inev.ie.code = keysym & 0xFFFFFF;
+	inev.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+      inev.code = keysym & 0xFFFFFF;
       goto done;
     }
 
@@ -6523,8 +6523,8 @@ xg_widget_key_press_event_cb (GtkWidget *widget, GdkEvent *event,
        /* Any "vendor-specific" key is ok.  */
        || (keysym & (1 << 28))))
     {
-      inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
-      inev.ie.code = keysym;
+      inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+      inev.code = keysym;
       goto done;
     }
 
@@ -6532,22 +6532,22 @@ xg_widget_key_press_event_cb (GtkWidget *widget, GdkEvent *event,
 
   if (uc)
     {
-      inev.ie.kind = (SINGLE_BYTE_CHAR_P (uc)
-		      ? ASCII_KEYSTROKE_EVENT
-		      : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-      inev.ie.code = uc;
+      inev.kind = (SINGLE_BYTE_CHAR_P (uc)
+		   ? ASCII_KEYSTROKE_EVENT
+		   : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+      inev.code = uc;
     }
   else
     {
-      inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
-      inev.ie.code = keysym;
+      inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+      inev.code = keysym;
     }
 
  done:
-  if (inev.ie.kind != NO_EVENT)
+  if (inev.kind != NO_EVENT)
     {
       xg_pending_quit_event.kind = NO_EVENT;
-      kbd_buffer_store_buffered_event (&inev, &xg_pending_quit_event);
+      kbd_buffer_store_event_hold (&inev, &xg_pending_quit_event);
     }
 
   XNoOp (FRAME_X_DISPLAY (f));
diff --git a/src/keyboard.c b/src/keyboard.c
index b22814d702d..ef84bda9664 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -408,7 +408,7 @@ #define READABLE_EVENTS_IGNORE_SQUEEZABLES	(1 << 2)
 static void deliver_user_signal (int);
 static char *find_user_signal_name (int);
 static void store_user_signal_events (void);
-static bool is_ignored_event (union buffered_input_event *);
+static bool is_ignored_event_kind (enum event_kind);
 
 /* Advance or retreat a buffered input event pointer.  */
 
@@ -3629,7 +3629,7 @@ readable_events (int flags)
 		      && (event->kind == FOCUS_IN_EVENT
 			  || event->kind == FOCUS_OUT_EVENT))
 		     || (input_pending_p_filter_events
-			 && is_ignored_event (event))))
+			 && is_ignored_event_kind (event->kind))))
 #ifdef USE_TOOLKIT_SCROLL_BARS
 		  && !((flags & READABLE_EVENTS_IGNORE_SQUEEZABLES)
 		       && (event->kind == SCROLL_BAR_CLICK_EVENT
@@ -3714,6 +3714,31 @@ kbd_buffer_store_event (register struct input_event *event)
   kbd_buffer_store_event_hold (event, 0);
 }
 
+static void
+beware_long_paste (void)
+{
+#ifdef subprocesses
+  if (! (kbd_buffer_nr_stored () <= KBD_BUFFER_SIZE / 2
+	 && kbd_on_hold_p ()))
+    {
+      /* Don't read keyboard input until we have processed kbd_buffer.
+	 This happens when pasting text longer than KBD_BUFFER_SIZE/2.  */
+      hold_keyboard_input ();
+      unrequest_sigio ();
+      stop_polling ();
+    }
+#endif
+}
+
+/* If we're inside while-no-input, and this event qualifies
+   as input, set quit-flag to cause an interrupt.  */
+static void
+maybe_quit_while_no_input (enum event_kind kind)
+{
+  if (!NILP (Vthrow_on_input) && !is_ignored_event_kind (kind))
+    Vquit_flag = Vthrow_on_input;
+}
+
 /* Store EVENT obtained at interrupt level into kbd_buffer, fifo.
 
    If HOLD_QUIT is 0, just stuff EVENT into the fifo.
@@ -3725,8 +3750,8 @@ kbd_buffer_store_event (register struct input_event *event)
    subsequent input events have been parsed (and discarded).  */
 
 void
-kbd_buffer_store_buffered_event (union buffered_input_event *event,
-				 struct input_event *hold_quit)
+kbd_buffer_store_event_hold (struct input_event const *event,
+			     struct input_event *hold_quit)
 {
   if (event->kind == NO_EVENT)
     emacs_abort ();
@@ -3736,23 +3761,23 @@ kbd_buffer_store_buffered_event (union buffered_input_event *event,
 
   if (event->kind == ASCII_KEYSTROKE_EVENT)
     {
-      int c = event->ie.code & 0377;
+      int c = event->code & 0377;
 
-      if (event->ie.modifiers & ctrl_modifier)
+      if (event->modifiers & ctrl_modifier)
 	c = make_ctrl_char (c);
 
-      c |= (event->ie.modifiers
+      c |= (event->modifiers
 	    & (meta_modifier | alt_modifier
 	       | hyper_modifier | super_modifier));
 
       if (c == quit_char)
 	{
-	  KBOARD *kb = FRAME_KBOARD (XFRAME (event->ie.frame_or_window));
+	  KBOARD *kb = FRAME_KBOARD (XFRAME (event->frame_or_window));
 
 	  if (single_kboard && kb != current_kboard)
 	    {
 	      kset_kbd_queue
-		(kb, list2 (make_lispy_switch_frame (event->ie.frame_or_window),
+		(kb, list2 (make_lispy_switch_frame (event->frame_or_window),
 			    make_fixnum (c)));
 	      kb->kbd_queue_has_data = true;
 
@@ -3771,7 +3796,7 @@ kbd_buffer_store_buffered_event (union buffered_input_event *event,
 
 	  if (hold_quit)
 	    {
-	      *hold_quit = event->ie;
+	      *hold_quit = *event;
 	      return;
 	    }
 
@@ -3782,9 +3807,9 @@ kbd_buffer_store_buffered_event (union buffered_input_event *event,
 	  {
 	    Lisp_Object focus;
 
-	    focus = FRAME_FOCUS_FRAME (XFRAME (event->ie.frame_or_window));
+	    focus = FRAME_FOCUS_FRAME (XFRAME (event->frame_or_window));
 	    if (NILP (focus))
-	      focus = event->ie.frame_or_window;
+	      focus = event->frame_or_window;
 	    internal_last_event_frame = focus;
 	    Vlast_event_frame = focus;
 	  }
@@ -3807,26 +3832,44 @@ kbd_buffer_store_buffered_event (union buffered_input_event *event,
   union buffered_input_event *next_slot = next_kbd_event (kbd_store_ptr);
   if (kbd_fetch_ptr != next_slot)
     {
-      *kbd_store_ptr = *event;
+      kbd_store_ptr->ie = *event;
       kbd_store_ptr = next_slot;
-#ifdef subprocesses
-      if (kbd_buffer_nr_stored () > KBD_BUFFER_SIZE / 2
-	  && ! kbd_on_hold_p ())
-        {
-          /* Don't read keyboard input until we have processed kbd_buffer.
-             This happens when pasting text longer than KBD_BUFFER_SIZE/2.  */
-          hold_keyboard_input ();
-          unrequest_sigio ();
-          stop_polling ();
-        }
-#endif	/* subprocesses */
+      beware_long_paste ();
     }
 
-  /* If we're inside while-no-input, and this event qualifies
-     as input, set quit-flag to cause an interrupt.  */
-  if (!NILP (Vthrow_on_input)
-      && !is_ignored_event (event))
-    Vquit_flag = Vthrow_on_input;
+  maybe_quit_while_no_input (event->kind);
+}
+
+/* Store EVENT obtained at interrupt level into kbd_buffer, fifo.
+   This is like kbd_buffer_store_event_hold, but for struct
+   selection_input_event instead of struct input_event.
+
+   If HOLD_QUIT && HOLD_QUIT->kind != NO_EVENT, discard EVENT.
+
+   This is used to postpone the processing of the quit event until all
+   subsequent input events have been parsed (and discarded).  */
+
+void
+kbd_buffer_store_selection_event_hold
+  (struct selection_input_event const *event,
+   struct input_event const *hold_quit)
+{
+  if (hold_quit && hold_quit->kind != NO_EVENT)
+    return;
+
+  /* Don't let the very last slot in the buffer become full,
+     since that would make the two pointers equal,
+     and that is indistinguishable from an empty buffer.
+     Discard the event if it would fill the last slot.  */
+  union buffered_input_event *next_slot = next_kbd_event (kbd_store_ptr);
+  if (kbd_fetch_ptr != next_slot)
+    {
+      kbd_store_ptr->sie = *event;
+      kbd_store_ptr = next_slot;
+      beware_long_paste ();
+    }
+
+  maybe_quit_while_no_input (event->kind);
 }
 
 /* Limit help event positions to this range, to avoid overflow problems.  */
@@ -12877,11 +12920,11 @@ init_while_no_input_ignore_events (void)
 }
 
 static bool
-is_ignored_event (union buffered_input_event *event)
+is_ignored_event_kind (enum event_kind kind)
 {
   Lisp_Object ignore_event;
 
-  switch (event->kind)
+  switch (kind)
     {
     case FOCUS_IN_EVENT: ignore_event = Qfocus_in; break;
     case FOCUS_OUT_EVENT: ignore_event = Qfocus_out; break;
diff --git a/src/keyboard.h b/src/keyboard.h
index 5e04b54eb74..99972944d28 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -499,17 +499,10 @@ #define EVENT_HEAD_KIND(event_head) \
 extern void swallow_events (bool);
 extern bool lucid_event_type_list_p (Lisp_Object);
 extern void kbd_buffer_store_event (struct input_event *);
-extern void kbd_buffer_store_buffered_event (union buffered_input_event *,
-					     struct input_event *);
-INLINE void
-kbd_buffer_store_event_hold (struct input_event *event,
-			     struct input_event *hold_quit)
-{
-  static_assert (alignof (struct input_event) == alignof (union buffered_input_event)
-		 && sizeof (struct input_event) == sizeof (union buffered_input_event));
-  kbd_buffer_store_buffered_event ((union buffered_input_event *) event,
-				   hold_quit);
-}
+extern void kbd_buffer_store_event_hold (struct input_event const *,
+					 struct input_event *);
+extern void kbd_buffer_store_selection_event_hold
+  (struct selection_input_event const *, struct input_event const *);
 extern void poll_for_input_1 (void);
 extern void show_help_echo (Lisp_Object, Lisp_Object, Lisp_Object,
                             Lisp_Object);
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index 00377ff73a0..0ef6084d2f4 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -286,12 +286,8 @@ flip_cr_context (struct frame *f)

 static void
-evq_enqueue (union buffered_input_event *ev)
+evq_grow_if_needed (struct event_queue_t *evq)
 {
-  struct event_queue_t *evq = &event_q;
-  struct frame *frame;
-  struct pgtk_display_info *dpyinfo;
-
   if (evq->cap == 0)
     {
       evq->cap = 4;
@@ -303,32 +299,48 @@ evq_enqueue (union buffered_input_event *ev)
       evq->cap += evq->cap / 2;
       evq->q = xrealloc (evq->q, sizeof *evq->q * evq->cap);
     }
+}
+
+static void
+evq_enqueue (struct input_event const *ev)
+{
+  struct event_queue_t *evq = &event_q;
+  struct frame *frame;
+  struct pgtk_display_info *dpyinfo;
 
-  evq->q[evq->nr++] = *ev;
+  evq_grow_if_needed (evq);
+  evq->q[evq->nr++].ie = *ev;
 
-  if (ev->ie.kind != SELECTION_REQUEST_EVENT
-      && ev->ie.kind != SELECTION_CLEAR_EVENT)
-    {
-      frame = NULL;
+  frame = NULL;
 
-      if (WINDOWP (ev->ie.frame_or_window))
-	frame = WINDOW_XFRAME (XWINDOW (ev->ie.frame_or_window));
+  if (WINDOWP (ev->frame_or_window))
+    frame = WINDOW_XFRAME (XWINDOW (ev->frame_or_window));
 
-      if (FRAMEP (ev->ie.frame_or_window))
-	frame = XFRAME (ev->ie.frame_or_window);
+  if (FRAMEP (ev->frame_or_window))
+    frame = XFRAME (ev->frame_or_window);
 
-      if (frame)
-	{
-	  dpyinfo = FRAME_DISPLAY_INFO (frame);
+  if (frame)
+    {
+      dpyinfo = FRAME_DISPLAY_INFO (frame);
 
-	  if (dpyinfo->last_user_time < ev->ie.timestamp)
-	    dpyinfo->last_user_time = ev->ie.timestamp;
-	}
+      if (dpyinfo->last_user_time < ev->timestamp)
+	dpyinfo->last_user_time = ev->timestamp;
     }
 
   raise (SIGIO);
 }
 
+static void
+evq_selection_enqueue (struct selection_input_event const *ev)
+{
+  struct event_queue_t *evq = &event_q;
+
+  evq_grow_if_needed (evq);
+  evq->q[evq->nr++].sie = *ev;
+
+  raise (SIGIO);
+}
+
 static int
 evq_flush (struct input_event *hold_quit)
 {
@@ -337,17 +349,27 @@ evq_flush (struct input_event *hold_quit)
 
   while (evq->nr > 0)
     {
-      /* kbd_buffer_store_buffered_event may do longjmp, so
-	 we need to shift event queue first and pass the event
-	 to kbd_buffer_store_buffered_event so that events in
+      /* Because kbd_buffer_store_event_hold and
+	 kbd_buffer_store_selection_event_hold may do longjmp,
+	 we need to shift event queue before passing a pointer
+	 to a copy of the event, so that events in
 	 queue are not processed twice.  Bug#52941 */
-      union buffered_input_event ev = evq->q[0];
-      int i;
-      for (i = 1; i < evq->nr; i++)
-	evq->q[i - 1] = evq->q[i];
       evq->nr--;
 
-      kbd_buffer_store_buffered_event (&ev, hold_quit);
+      if (evq->q[0].kind == SELECTION_REQUEST_EVENT
+	  || evq->q[0].kind == SELECTION_CLEAR_EVENT)
+	{
+	  struct selection_input_event sinev = evq->q[0].sie;
+	  memmove (&evq->q[0], &evq->q[1], evq->nr * sizeof evq->q[0]);
+	  kbd_buffer_store_selection_event_hold (&sinev, hold_quit);
+	}
+      else
+	{
+	  struct input_event inev = evq->q[0].ie;
+	  memmove (&evq->q[0], &evq->q[1], evq->nr * sizeof evq->q[0]);
+	  kbd_buffer_store_event_hold (&inev, hold_quit);
+	}
+
       n++;
     }
 
@@ -3928,21 +3950,21 @@ pgtk_read_socket (struct terminal *terminal, struct input_event *hold_quit)
 pgtk_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
 			    int portion, int whole, bool horizontal)
 {
-  union buffered_input_event inev;
+  struct input_event inev;
 
-  EVENT_INIT (inev.ie);
+  EVENT_INIT (inev);
 
-  inev.ie.kind = (horizontal
-		  ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
-		  : SCROLL_BAR_CLICK_EVENT);
-  inev.ie.frame_or_window = window;
-  inev.ie.arg = Qnil;
-  inev.ie.timestamp = 0;
-  inev.ie.code = 0;
-  inev.ie.part = part;
-  inev.ie.x = make_fixnum (portion);
-  inev.ie.y = make_fixnum (whole);
-  inev.ie.modifiers = 0;
+  inev.kind = (horizontal
+	       ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT
+	       : SCROLL_BAR_CLICK_EVENT);
+  inev.frame_or_window = window;
+  inev.arg = Qnil;
+  inev.timestamp = 0;
+  inev.code = 0;
+  inev.part = part;
+  inev.x = make_fixnum (portion);
+  inev.y = make_fixnum (whole);
+  inev.modifiers = 0;
 
   evq_enqueue (&inev);
 }
@@ -4942,7 +4964,6 @@ pgtk_any_window_to_frame (GdkWindow *window)
 pgtk_handle_event (GtkWidget *widget, GdkEvent *event, gpointer *data)
 {
   struct frame *f;
-  union buffered_input_event inev;
   GtkWidget *frame_widget;
   gint x, y;
 
@@ -4959,18 +4980,18 @@ pgtk_handle_event (GtkWidget *widget, GdkEvent *event, gpointer *data)
 					&x, &y);
       if (f)
 	{
-
-	  inev.ie.kind = PINCH_EVENT;
-	  XSETFRAME (inev.ie.frame_or_window, f);
-	  XSETINT (inev.ie.x, x);
-	  XSETINT (inev.ie.y, y);
-	  inev.ie.arg = list4 (make_float (event->touchpad_pinch.dx),
-			       make_float (event->touchpad_pinch.dy),
-			       make_float (event->touchpad_pinch.scale),
-			       make_float (event->touchpad_pinch.angle_delta));
-	  inev.ie.modifiers = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f),
+	  struct input_event inev;
+	  inev.kind = PINCH_EVENT;
+	  XSETFRAME (inev.frame_or_window, f);
+	  XSETINT (inev.x, x);
+	  XSETINT (inev.y, y);
+	  inev.arg = list4 (make_float (event->touchpad_pinch.dx),
+			    make_float (event->touchpad_pinch.dy),
+			    make_float (event->touchpad_pinch.scale),
+			    make_float (event->touchpad_pinch.angle_delta));
+	  inev.modifiers = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f),
 							   event->touchpad_pinch.state);
-	  inev.ie.device
+	  inev.device
 	    = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
 	  evq_enqueue (&inev);
 	}
@@ -5188,17 +5209,17 @@ pgtk_enqueue_string (struct frame *f, gchar *str)
     return;
   for (; *ustr != 0; ustr++)
     {
-      union buffered_input_event inev;
+      struct input_event inev;
       Lisp_Object c = make_fixnum (*ustr);
-      EVENT_INIT (inev.ie);
-      inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
-		      ? ASCII_KEYSTROKE_EVENT
-		      : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-      inev.ie.arg = Qnil;
-      inev.ie.code = XFIXNAT (c);
-      XSETFRAME (inev.ie.frame_or_window, f);
-      inev.ie.modifiers = 0;
-      inev.ie.timestamp = 0;
+      EVENT_INIT (inev);
+      inev.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
+		   ? ASCII_KEYSTROKE_EVENT
+		   : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+      inev.arg = Qnil;
+      inev.code = XFIXNAT (c);
+      XSETFRAME (inev.frame_or_window, f);
+      inev.modifiers = 0;
+      inev.timestamp = 0;
       evq_enqueue (&inev);
     }
 
@@ -5208,28 +5229,28 @@ pgtk_enqueue_string (struct frame *f, gchar *str)
 void
 pgtk_enqueue_preedit (struct frame *f, Lisp_Object preedit)
 {
-  union buffered_input_event inev;
-  EVENT_INIT (inev.ie);
-  inev.ie.kind = PREEDIT_TEXT_EVENT;
-  inev.ie.arg = preedit;
-  inev.ie.code = 0;
-  XSETFRAME (inev.ie.frame_or_window, f);
-  inev.ie.modifiers = 0;
-  inev.ie.timestamp = 0;
+  struct input_event inev;
+  EVENT_INIT (inev);
+  inev.kind = PREEDIT_TEXT_EVENT;
+  inev.arg = preedit;
+  inev.code = 0;
+  XSETFRAME (inev.frame_or_window, f);
+  inev.modifiers = 0;
+  inev.timestamp = 0;
   evq_enqueue (&inev);
 }
 
 static gboolean
 key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
 {
-  union buffered_input_event inev;
+  struct input_event inev;
   ptrdiff_t nbytes;
   Mouse_HLInfo *hlinfo;
   struct frame *f;
   struct pgtk_display_info *dpyinfo;
 
   f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
-  EVENT_INIT (inev.ie);
+  EVENT_INIT (inev);
   hlinfo = MOUSE_HL_INFO (f);
   nbytes = 0;
 
@@ -5300,20 +5321,20 @@ key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
       orig_keysym = keysym;
 
       /* Common for all keysym input events.  */
-      XSETFRAME (inev.ie.frame_or_window, f);
-      inev.ie.modifiers
+      XSETFRAME (inev.frame_or_window, f);
+      inev.modifiers
 	= pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), modifiers);
-      inev.ie.timestamp = event->key.time;
+      inev.timestamp = event->key.time;
 
       /* First deal with keysyms which have defined
          translations to characters.  */
       if (keysym >= 32 && keysym < 128)
 	/* Avoid explicitly decoding each ASCII character.  */
 	{
-	  inev.ie.kind = ASCII_KEYSTROKE_EVENT;
-	  inev.ie.code = keysym;
+	  inev.kind = ASCII_KEYSTROKE_EVENT;
+	  inev.code = keysym;
 
-	  inev.ie.device
+	  inev.device
 	    = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
 	  goto done;
 	}
@@ -5322,12 +5343,12 @@ key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
       if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
 	{
 	  if (keysym < 0x01000080)
-	    inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+	    inev.kind = ASCII_KEYSTROKE_EVENT;
 	  else
-	    inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
-	  inev.ie.code = keysym & 0xFFFFFF;
+	    inev.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+	  inev.code = keysym & 0xFFFFFF;
 
-	  inev.ie.device
+	  inev.device
 	    = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
 	  goto done;
 	}
@@ -5337,12 +5358,12 @@ key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
 	  && (c = Fgethash (make_fixnum (keysym),
 			    Vpgtk_keysym_table, Qnil), FIXNATP (c)))
 	{
-	  inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
-			  ? ASCII_KEYSTROKE_EVENT
-			  : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-	  inev.ie.code = XFIXNAT (c);
+	  inev.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
+		       ? ASCII_KEYSTROKE_EVENT
+		       : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+	  inev.code = XFIXNAT (c);
 
-	  inev.ie.device
+	  inev.device
 	    = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
 	  goto done;
 	}
@@ -5421,18 +5442,18 @@ key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
 	{
 	  /* make_lispy_event will convert this to a symbolic
 	     key.  */
-	  inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
-	  inev.ie.code = keysym;
+	  inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+	  inev.code = keysym;
 
-	  inev.ie.device
+	  inev.device
 	    = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
 	  goto done;
 	}
 
       {
-	inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
-	inev.ie.arg = make_unibyte_string ((char *) copy_bufptr, nbytes);
-	inev.ie.device
+	inev.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+	inev.arg = make_unibyte_string ((char *) copy_bufptr, nbytes);
+	inev.device
 	  = pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
 
 	if (keysym == GDK_KEY_VoidSymbol)
@@ -5441,9 +5462,9 @@ key_press_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
     }
 
 done:
-  if (inev.ie.kind != NO_EVENT)
+  if (inev.kind != NO_EVENT)
     {
-      XSETFRAME (inev.ie.frame_or_window, f);
+      XSETFRAME (inev.frame_or_window, f);
       evq_enqueue (&inev);
     }
 
@@ -5522,11 +5543,11 @@ map_event (GtkWidget *widget,
 	   gpointer *user_data)
 {
   struct frame *f = pgtk_any_window_to_frame (event->any.window);
-  union buffered_input_event inev;
+  struct input_event inev;
 
-  EVENT_INIT (inev.ie);
-  inev.ie.kind = NO_EVENT;
-  inev.ie.arg = Qnil;
+  EVENT_INIT (inev);
+  inev.kind = NO_EVENT;
+  inev.arg = Qnil;
 
   if (f)
     {
@@ -5553,12 +5574,12 @@ map_event (GtkWidget *widget,
 
       if (iconified)
 	{
-	  inev.ie.kind = DEICONIFY_EVENT;
-	  XSETFRAME (inev.ie.frame_or_window, f);
+	  inev.kind = DEICONIFY_EVENT;
+	  XSETFRAME (inev.frame_or_window, f);
 	}
     }
 
-  if (inev.ie.kind != NO_EVENT)
+  if (inev.kind != NO_EVENT)
     evq_enqueue (&inev);
   return FALSE;
 }
@@ -5570,13 +5591,13 @@ window_state_event (GtkWidget *widget,
 {
   struct frame *f = pgtk_any_window_to_frame (event->window_state.window);
   GdkWindowState new_state;
-  union buffered_input_event inev;
+  struct input_event inev;
 
   new_state = event->window_state.new_window_state;
 
-  EVENT_INIT (inev.ie);
-  inev.ie.kind = NO_EVENT;
-  inev.ie.arg = Qnil;
+  EVENT_INIT (inev);
+  inev.kind = NO_EVENT;
+  inev.arg = Qnil;
 
   if (new_state & GDK_WINDOW_STATE_FULLSCREEN)
     store_frame_param (f, Qfullscreen, Qfullboth);
@@ -5622,8 +5643,8 @@ window_state_event (GtkWidget *widget,
   else
     {
       FRAME_X_OUTPUT (f)->has_been_visible = true;
-      inev.ie.kind = DEICONIFY_EVENT;
-      XSETFRAME (inev.ie.frame_or_window, f);
+      inev.kind = DEICONIFY_EVENT;
+      XSETFRAME (inev.frame_or_window, f);
       SET_FRAME_ICONIFIED (f, false);
       SET_FRAME_VISIBLE (f, true);
     }
@@ -5633,7 +5654,7 @@ window_state_event (GtkWidget *widget,
   else
     store_frame_param (f, Qsticky, Qnil);
 
-  if (inev.ie.kind != NO_EVENT)
+  if (inev.kind != NO_EVENT)
     evq_enqueue (&inev);
   return FALSE;
 }
@@ -5643,19 +5664,19 @@ delete_event (GtkWidget *widget,
 	      GdkEvent *event, gpointer *user_data)
 {
   struct frame *f = pgtk_any_window_to_frame (event->any.window);
-  union buffered_input_event inev;
+  struct input_event inev;
 
-  EVENT_INIT (inev.ie);
-  inev.ie.kind = NO_EVENT;
-  inev.ie.arg = Qnil;
+  EVENT_INIT (inev);
+  inev.kind = NO_EVENT;
+  inev.arg = Qnil;
 
   if (f)
     {
-      inev.ie.kind = DELETE_WINDOW_EVENT;
-      XSETFRAME (inev.ie.frame_or_window, f);
+      inev.kind = DELETE_WINDOW_EVENT;
+      XSETFRAME (inev.frame_or_window, f);
     }
 
-  if (inev.ie.kind != NO_EVENT)
+  if (inev.kind != NO_EVENT)
     evq_enqueue (&inev);
   return TRUE;
 }
@@ -5672,7 +5693,7 @@ delete_event (GtkWidget *widget,
 static void
 pgtk_focus_changed (gboolean is_enter, int state,
 		    struct pgtk_display_info *dpyinfo, struct frame *frame,
-		    union buffered_input_event *bufp)
+		    struct input_event *bufp)
 {
   if (is_enter)
     {
@@ -5684,13 +5705,13 @@ pgtk_focus_changed (gboolean is_enter, int state,
 	  /* Don't stop displaying the initial startup message
 	     for a switch-frame event we don't need.  */
 	  /* When run as a daemon, Vterminal_frame is always NIL.  */
-	  bufp->ie.arg = (((NILP (Vterminal_frame)
-			    || !FRAME_PGTK_P (XFRAME (Vterminal_frame))
-			    || EQ (Fdaemonp (), Qt))
-			   && CONSP (Vframe_list)
-			   && !NILP (XCDR (Vframe_list))) ? Qt : Qnil);
-	  bufp->ie.kind = FOCUS_IN_EVENT;
-	  XSETFRAME (bufp->ie.frame_or_window, frame);
+	  bufp->arg = (((NILP (Vterminal_frame)
+			 || !FRAME_PGTK_P (XFRAME (Vterminal_frame))
+			 || EQ (Fdaemonp (), Qt))
+			&& CONSP (Vframe_list)
+			&& !NILP (XCDR (Vframe_list))) ? Qt : Qnil);
+	  bufp->kind = FOCUS_IN_EVENT;
+	  XSETFRAME (bufp->frame_or_window, frame);
 	}
 
       frame->output_data.pgtk->focus_state |= state;
@@ -5705,8 +5726,8 @@ pgtk_focus_changed (gboolean is_enter, int state,
           dpyinfo->x_focus_event_frame = 0;
           pgtk_new_focus_frame (dpyinfo, NULL);
 
-          bufp->ie.kind = FOCUS_OUT_EVENT;
-          XSETFRAME (bufp->ie.frame_or_window, frame);
+	  bufp->kind = FOCUS_OUT_EVENT;
+	  XSETFRAME (bufp->frame_or_window, frame);
         }
 
       if (frame->pointer_invisible)
@@ -5718,7 +5739,7 @@ pgtk_focus_changed (gboolean is_enter, int state,
 enter_notify_event (GtkWidget *widget, GdkEvent *event,
 		    gpointer *user_data)
 {
-  union buffered_input_event inev;
+  struct input_event inev;
   struct frame *frame
     = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
 
@@ -5730,14 +5751,14 @@ enter_notify_event (GtkWidget *widget, GdkEvent *event,
   int focus_state
     = focus_frame ? focus_frame->output_data.pgtk->focus_state : 0;
 
-  EVENT_INIT (inev.ie);
-  inev.ie.kind = NO_EVENT;
-  inev.ie.arg = Qnil;
+  EVENT_INIT (inev);
+  inev.kind = NO_EVENT;
+  inev.arg = Qnil;
 
   if (event->crossing.detail != GDK_NOTIFY_INFERIOR
       && event->crossing.focus && !(focus_state & FOCUS_EXPLICIT))
     pgtk_focus_changed (TRUE, FOCUS_IMPLICIT, dpyinfo, frame, &inev);
-  if (inev.ie.kind != NO_EVENT)
+  if (inev.kind != NO_EVENT)
     evq_enqueue (&inev);
   return TRUE;
 }
@@ -5746,7 +5767,7 @@ enter_notify_event (GtkWidget *widget, GdkEvent *event,
 leave_notify_event (GtkWidget *widget, GdkEvent *event,
 		    gpointer *user_data)
 {
-  union buffered_input_event inev;
+  struct input_event inev;
   struct frame *frame
     = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
 
@@ -5767,9 +5788,9 @@ leave_notify_event (GtkWidget *widget, GdkEvent *event,
       hlinfo->mouse_face_mouse_frame = 0;
     }
 
-  EVENT_INIT (inev.ie);
-  inev.ie.kind = NO_EVENT;
-  inev.ie.arg = Qnil;
+  EVENT_INIT (inev);
+  inev.kind = NO_EVENT;
+  inev.arg = Qnil;
 
   if (event->crossing.detail != GDK_NOTIFY_INFERIOR
       && event->crossing.focus && !(focus_state & FOCUS_EXPLICIT))
@@ -5786,7 +5807,7 @@ leave_notify_event (GtkWidget *widget, GdkEvent *event,
 	}
     }
 
-  if (inev.ie.kind != NO_EVENT)
+  if (inev.kind != NO_EVENT)
     evq_enqueue (&inev);
   return TRUE;
 }
@@ -5794,20 +5815,20 @@ leave_notify_event (GtkWidget *widget, GdkEvent *event,
 static gboolean
 focus_in_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
 {
-  union buffered_input_event inev;
+  struct input_event inev;
   struct frame *frame
     = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
 
   if (frame == NULL)
     return TRUE;
 
-  EVENT_INIT (inev.ie);
-  inev.ie.kind = NO_EVENT;
-  inev.ie.arg = Qnil;
+  EVENT_INIT (inev);
+  inev.kind = NO_EVENT;
+  inev.arg = Qnil;
 
   pgtk_focus_changed (TRUE, FOCUS_EXPLICIT,
 		      FRAME_DISPLAY_INFO (frame), frame, &inev);
-  if (inev.ie.kind != NO_EVENT)
+  if (inev.kind != NO_EVENT)
     evq_enqueue (&inev);
 
   pgtk_im_focus_in (frame);
@@ -5818,20 +5839,20 @@ focus_in_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
 static gboolean
 focus_out_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
 {
-  union buffered_input_event inev;
+  struct input_event inev;
   struct frame *frame
     = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
 
   if (frame == NULL)
     return TRUE;
 
-  EVENT_INIT (inev.ie);
-  inev.ie.kind = NO_EVENT;
-  inev.ie.arg = Qnil;
+  EVENT_INIT (inev);
+  inev.kind = NO_EVENT;
+  inev.arg = Qnil;
 
   pgtk_focus_changed (FALSE, FOCUS_EXPLICIT,
 		      FRAME_DISPLAY_INFO (frame), frame, &inev);
-  if (inev.ie.kind != NO_EVENT)
+  if (inev.kind != NO_EVENT)
     evq_enqueue (&inev);
 
   pgtk_im_focus_out (frame);
@@ -5901,7 +5922,7 @@ note_mouse_movement (struct frame *frame,
 motion_notify_event (GtkWidget *widget, GdkEvent *event,
 		     gpointer *user_data)
 {
-  union buffered_input_event inev;
+  struct input_event inev;
   struct frame *f, *frame;
   struct pgtk_display_info *dpyinfo;
   Mouse_HLInfo *hlinfo;
@@ -5917,9 +5938,9 @@ motion_notify_event (GtkWidget *widget, GdkEvent *event,
 	  && (gdk_device_get_source (device) == GDK_SOURCE_TOUCHSCREEN)))
     return FALSE;
 
-  EVENT_INIT (inev.ie);
-  inev.ie.kind = NO_EVENT;
-  inev.ie.arg = Qnil;
+  EVENT_INIT (inev);
+  inev.kind = NO_EVENT;
+  inev.arg = Qnil;
 
   previous_help_echo_string = help_echo_string;
   help_echo_string = Qnil;
@@ -5970,8 +5991,8 @@ motion_notify_event (GtkWidget *widget, GdkEvent *event,
 	      && !EQ (window, last_mouse_window)
 	      && !EQ (window, selected_window))
 	    {
-	      inev.ie.kind = SELECT_WINDOW_EVENT;
-	      inev.ie.frame_or_window = window;
+	      inev.kind = SELECT_WINDOW_EVENT;
+	      inev.frame_or_window = window;
 	    }
 
 	  /* Remember the last window where we saw the mouse.  */
@@ -5992,7 +6013,7 @@ motion_notify_event (GtkWidget *widget, GdkEvent *event,
   if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
     do_help = 1;
 
-  if (inev.ie.kind != NO_EVENT)
+  if (inev.kind != NO_EVENT)
     evq_enqueue (&inev);
 
   if (do_help > 0)
@@ -6045,7 +6066,7 @@ construct_mouse_click (struct input_event *result,
 button_event (GtkWidget *widget, GdkEvent *event,
 	      gpointer *user_data)
 {
-  union buffered_input_event inev;
+  struct input_event inev;
   struct frame *f, *frame;
   struct pgtk_display_info *dpyinfo;
 
@@ -6066,9 +6087,9 @@ button_event (GtkWidget *widget, GdkEvent *event,
 	  && (gdk_device_get_source (device) == GDK_SOURCE_TOUCHSCREEN)))
     return FALSE;
 
-  EVENT_INIT (inev.ie);
-  inev.ie.kind = NO_EVENT;
-  inev.ie.arg = Qnil;
+  EVENT_INIT (inev);
+  inev.kind = NO_EVENT;
+  inev.arg = Qnil;
 
   /* ignore double click and triple click. */
   if (event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE)
@@ -6137,16 +6158,16 @@ button_event (GtkWidget *widget, GdkEvent *event,
 		  && event->button.time > ignore_next_mouse_click_timeout)
 		{
 		  ignore_next_mouse_click_timeout = 0;
-		  construct_mouse_click (&inev.ie, &event->button, f);
+		  construct_mouse_click (&inev, &event->button, f);
 		}
 	      if (event->type == GDK_BUTTON_RELEASE)
 		ignore_next_mouse_click_timeout = 0;
 	    }
 	  else
-	    construct_mouse_click (&inev.ie, &event->button, f);
+	    construct_mouse_click (&inev, &event->button, f);
 
 	  if (!NILP (tab_bar_arg))
-	    inev.ie.arg = tab_bar_arg;
+	    inev.arg = tab_bar_arg;
 	}
     }
 
@@ -6168,7 +6189,7 @@ button_event (GtkWidget *widget, GdkEvent *event,
   if (f != 0)
     f->mouse_moved = false;
 
-  if (inev.ie.kind != NO_EVENT)
+  if (inev.kind != NO_EVENT)
     evq_enqueue (&inev);
   return TRUE;
 }
@@ -6176,15 +6197,15 @@ button_event (GtkWidget *widget, GdkEvent *event,
 static gboolean
 scroll_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
 {
-  union buffered_input_event inev;
+  struct input_event inev;
   struct frame *f, *frame;
   struct pgtk_display_info *dpyinfo;
   GdkScrollDirection dir;
   double delta_x, delta_y;
 
-  EVENT_INIT (inev.ie);
-  inev.ie.kind = NO_EVENT;
-  inev.ie.arg = Qnil;
+  EVENT_INIT (inev);
+  inev.kind = NO_EVENT;
+  inev.arg = Qnil;
 
   frame = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
   dpyinfo = FRAME_DISPLAY_INFO (frame);
@@ -6194,19 +6215,19 @@ scroll_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
   else
     f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
 
-  inev.ie.kind = NO_EVENT;
-  inev.ie.timestamp = event->scroll.time;
-  inev.ie.modifiers
+  inev.kind = NO_EVENT;
+  inev.timestamp = event->scroll.time;
+  inev.modifiers
     = pgtk_gtk_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), event->scroll.state);
-  XSETINT (inev.ie.x, event->scroll.x);
-  XSETINT (inev.ie.y, event->scroll.y);
-  XSETFRAME (inev.ie.frame_or_window, f);
-  inev.ie.arg = Qnil;
+  XSETINT (inev.x, event->scroll.x);
+  XSETINT (inev.y, event->scroll.y);
+  XSETFRAME (inev.frame_or_window, f);
+  inev.arg = Qnil;
 
   if (gdk_event_is_scroll_stop_event (event))
     {
-      inev.ie.kind = TOUCH_END_EVENT;
-      inev.ie.device
+      inev.kind = TOUCH_END_EVENT;
+      inev.device
 	= pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
       evq_enqueue (&inev);
       return TRUE;
@@ -6217,20 +6238,20 @@ scroll_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
       switch (dir)
 	{
 	case GDK_SCROLL_UP:
-	  inev.ie.kind = WHEEL_EVENT;
-	  inev.ie.modifiers |= up_modifier;
+	  inev.kind = WHEEL_EVENT;
+	  inev.modifiers |= up_modifier;
 	  break;
 	case GDK_SCROLL_DOWN:
-	  inev.ie.kind = WHEEL_EVENT;
-	  inev.ie.modifiers |= down_modifier;
+	  inev.kind = WHEEL_EVENT;
+	  inev.modifiers |= down_modifier;
 	  break;
 	case GDK_SCROLL_LEFT:
-	  inev.ie.kind = HORIZ_WHEEL_EVENT;
-	  inev.ie.modifiers |= up_modifier;
+	  inev.kind = HORIZ_WHEEL_EVENT;
+	  inev.modifiers |= up_modifier;
 	  break;
 	case GDK_SCROLL_RIGHT:
-	  inev.ie.kind = HORIZ_WHEEL_EVENT;
-	  inev.ie.modifiers |= down_modifier;
+	  inev.kind = HORIZ_WHEEL_EVENT;
+	  inev.modifiers |= down_modifier;
 	  break;
 	case GDK_SCROLL_SMOOTH:		/* shut up warning */
 	  break;
@@ -6240,14 +6261,14 @@ scroll_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
     {
       if (!mwheel_coalesce_scroll_events)
 	{
-	  inev.ie.kind = ((fabs (delta_x) > fabs (delta_y))
-			  ? HORIZ_WHEEL_EVENT
-			  : WHEEL_EVENT);
-	  inev.ie.modifiers |= (inev.ie.kind == HORIZ_WHEEL_EVENT
-				? (delta_x >= 0 ? up_modifier : down_modifier)
-				: (delta_y >= 0 ? down_modifier : up_modifier));
-	  inev.ie.arg = list3 (Qnil, make_float (-delta_x * 100),
-			       make_float (-delta_y * 100));
+	  inev.kind = ((fabs (delta_x) > fabs (delta_y))
+		       ? HORIZ_WHEEL_EVENT
+		       : WHEEL_EVENT);
+	  inev.modifiers |= (inev.kind == HORIZ_WHEEL_EVENT
+			     ? (delta_x >= 0 ? up_modifier : down_modifier)
+			     : (delta_y >= 0 ? down_modifier : up_modifier));
+	  inev.arg = list3 (Qnil, make_float (-delta_x * 100),
+			    make_float (-delta_y * 100));
 	}
       else
 	{
@@ -6256,21 +6277,21 @@ scroll_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
 	  if (dpyinfo->scroll.acc_y >= dpyinfo->scroll.y_per_line)
 	    {
 	      int nlines = dpyinfo->scroll.acc_y / dpyinfo->scroll.y_per_line;
-	      inev.ie.kind = WHEEL_EVENT;
-	      inev.ie.modifiers |= down_modifier;
-	      inev.ie.arg = list3 (make_fixnum (nlines),
-				   make_float (-dpyinfo->scroll.acc_x * 100),
-				   make_float (-dpyinfo->scroll.acc_y * 100));
+	      inev.kind = WHEEL_EVENT;
+	      inev.modifiers |= down_modifier;
+	      inev.arg = list3 (make_fixnum (nlines),
+				make_float (-dpyinfo->scroll.acc_x * 100),
+				make_float (-dpyinfo->scroll.acc_y * 100));
 	      dpyinfo->scroll.acc_y -= dpyinfo->scroll.y_per_line * nlines;
 	    }
 	  else if (dpyinfo->scroll.acc_y <= -dpyinfo->scroll.y_per_line)
 	    {
 	      int nlines = -dpyinfo->scroll.acc_y / dpyinfo->scroll.y_per_line;
-	      inev.ie.kind = WHEEL_EVENT;
-	      inev.ie.modifiers |= up_modifier;
-	      inev.ie.arg = list3 (make_fixnum (nlines),
-				   make_float (-dpyinfo->scroll.acc_x * 100),
-				   make_float (-dpyinfo->scroll.acc_y * 100));
+	      inev.kind = WHEEL_EVENT;
+	      inev.modifiers |= up_modifier;
+	      inev.arg = list3 (make_fixnum (nlines),
+				make_float (-dpyinfo->scroll.acc_x * 100),
+				make_float (-dpyinfo->scroll.acc_y * 100));
 
 	      dpyinfo->scroll.acc_y -= -dpyinfo->scroll.y_per_line * nlines;
 	    }
@@ -6278,31 +6299,31 @@ scroll_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data)
 		   || !mwheel_coalesce_scroll_events)
 	    {
 	      int nchars = dpyinfo->scroll.acc_x / dpyinfo->scroll.x_per_char;
-	      inev.ie.kind = HORIZ_WHEEL_EVENT;
-	      inev.ie.modifiers |= up_modifier;
-	      inev.ie.arg = list3 (make_fixnum (nchars),
-				   make_float (-dpyinfo->scroll.acc_x * 100),
-				   make_float (-dpyinfo->scroll.acc_y * 100));
+	      inev.kind = HORIZ_WHEEL_EVENT;
+	      inev.modifiers |= up_modifier;
+	      inev.arg = list3 (make_fixnum (nchars),
+				make_float (-dpyinfo->scroll.acc_x * 100),
+				make_float (-dpyinfo->scroll.acc_y * 100));
 
 	      dpyinfo->scroll.acc_x -= dpyinfo->scroll.x_per_char * nchars;
 	    }
 	  else if (dpyinfo->scroll.acc_x <= -dpyinfo->scroll.x_per_char)
 	    {
 	      int nchars = -dpyinfo->scroll.acc_x / dpyinfo->scroll.x_per_char;
-	      inev.ie.kind = HORIZ_WHEEL_EVENT;
-	      inev.ie.modifiers |= down_modifier;
-	      inev.ie.arg = list3 (make_fixnum (nchars),
-				   make_float (-dpyinfo->scroll.acc_x * 100),
-				   make_float (-dpyinfo->scroll.acc_y * 100));
+	      inev.kind = HORIZ_WHEEL_EVENT;
+	      inev.modifiers |= down_modifier;
+	      inev.arg = list3 (make_fixnum (nchars),
+				make_float (-dpyinfo->scroll.acc_x * 100),
+				make_float (-dpyinfo->scroll.acc_y * 100));
 
 	      dpyinfo->scroll.acc_x -= -dpyinfo->scroll.x_per_char * nchars;
 	    }
 	}
     }
 
-  if (inev.ie.kind != NO_EVENT)
+  if (inev.kind != NO_EVENT)
     {
-      inev.ie.device
+      inev.device
 	= pgtk_get_device_for_event (FRAME_DISPLAY_INFO (f), event);
       evq_enqueue (&inev);
     }
@@ -6397,7 +6418,7 @@ drag_leave (GtkWidget *widget, GdkDragContext *context,
 	    guint time, gpointer user_data)
 {
   struct frame *f;
-  union buffered_input_event inev;
+  struct input_event inev;
 
   f = pgtk_any_window_to_frame (gtk_widget_get_window (widget));
 
@@ -6411,16 +6432,16 @@ drag_leave (GtkWidget *widget, GdkDragContext *context,
 		       g_object_unref);
     }
 
-  EVENT_INIT (inev.ie);
+  EVENT_INIT (inev);
 
-  inev.ie.kind = DRAG_N_DROP_EVENT;
-  inev.ie.modifiers = 0;
-  inev.ie.arg = Qnil;
-  inev.ie.timestamp = time;
+  inev.kind = DRAG_N_DROP_EVENT;
+  inev.modifiers = 0;
+  inev.arg = Qnil;
+  inev.timestamp = time;
 
-  XSETINT (inev.ie.x, 0);
-  XSETINT (inev.ie.y, 0);
-  XSETFRAME (inev.ie.frame_or_window, f);
+  XSETINT (inev.x, 0);
+  XSETINT (inev.y, 0);
+  XSETFRAME (inev.frame_or_window, f);
 
   evq_enqueue (&inev);
 }
@@ -6431,7 +6452,7 @@ drag_motion (GtkWidget *widget, GdkDragContext *context,
 
 {
   struct frame *f;
-  union buffered_input_event inev;
+  struct input_event inev;
   GdkAtom name;
   GdkDragAction suggestion;
 
@@ -6457,18 +6478,18 @@ drag_motion (GtkWidget *widget, GdkDragContext *context,
   name = gdk_drag_get_selection (context);
   suggestion = gdk_drag_context_get_suggested_action (context);
 
-  EVENT_INIT (inev.ie);
+  EVENT_INIT (inev);
 
-  inev.ie.kind = DRAG_N_DROP_EVENT;
-  inev.ie.modifiers = 0;
-  inev.ie.arg = list4 (Qlambda, intern (gdk_atom_name (name)),
-		       make_uint (time),
-		       drag_action_to_symbol (suggestion));
-  inev.ie.timestamp = time;
+  inev.kind = DRAG_N_DROP_EVENT;
+  inev.modifiers = 0;
+  inev.arg = list4 (Qlambda, intern (gdk_atom_name (name)),
+		    make_uint (time),
+		    drag_action_to_symbol (suggestion));
+  inev.timestamp = time;
 
-  XSETINT (inev.ie.x, x);
-  XSETINT (inev.ie.y, y);
-  XSETFRAME (inev.ie.frame_or_window, f);
+  XSETINT (inev.x, x);
+  XSETINT (inev.y, y);
+  XSETFRAME (inev.frame_or_window, f);
 
   evq_enqueue (&inev);
 
@@ -6480,7 +6501,7 @@ drag_drop (GtkWidget *widget, GdkDragContext *context,
 	   int x, int y, guint time, gpointer user_data)
 {
   struct frame *f;
-  union buffered_input_event inev;
+  struct input_event inev;
   GdkAtom name;
   GdkDragAction selected_action;
 
@@ -6506,18 +6527,18 @@ drag_drop (GtkWidget *widget, GdkDragContext *context,
   name = gdk_drag_get_selection (context);
   selected_action = gdk_drag_context_get_selected_action (context);
 
-  EVENT_INIT (inev.ie);
+  EVENT_INIT (inev);
 
-  inev.ie.kind = DRAG_N_DROP_EVENT;
-  inev.ie.modifiers = 0;
-  inev.ie.arg = list4 (Qquote, intern (gdk_atom_name (name)),
-		       make_uint (time),
-		       drag_action_to_symbol (selected_action));
-  inev.ie.timestamp = time;
+  inev.kind = DRAG_N_DROP_EVENT;
+  inev.modifiers = 0;
+  inev.arg = list4 (Qquote, intern (gdk_atom_name (name)),
+		    make_uint (time),
+		    drag_action_to_symbol (selected_action));
+  inev.timestamp = time;
 
-  XSETINT (inev.ie.x, x);
-  XSETINT (inev.ie.y, y);
-  XSETFRAME (inev.ie.frame_or_window, f);
+  XSETINT (inev.x, x);
+  XSETINT (inev.y, y);
+  XSETFRAME (inev.frame_or_window, f);
 
   evq_enqueue (&inev);
 
@@ -6645,12 +6666,12 @@ touch_event_cb (GtkWidget *self, GdkEvent *event, gpointer user_data)
   struct pgtk_display_info *dpyinfo;
   struct frame *f;
   EMACS_INT local_detail;
-  union buffered_input_event inev;
+  struct input_event inev;
   struct pgtk_touch_point *touchpoint;
   Lisp_Object arg = Qnil;
   int state;
 
-  EVENT_INIT (inev.ie);
+  EVENT_INIT (inev);
 
   f = pgtk_any_window_to_frame (gtk_widget_get_window (self));
   eassert (f);
@@ -6669,12 +6690,12 @@ touch_event_cb (GtkWidget *self, GdkEvent *event, gpointer user_data)
 					    event->touch.x, event->touch.y,
 					    f);
       /* Generate the input event.  */
-      inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT;
-      inev.ie.timestamp = event->touch.time;
-      XSETFRAME (inev.ie.frame_or_window, f);
-      XSETINT (inev.ie.x, lrint (event->touch.x));
-      XSETINT (inev.ie.y, lrint (event->touch.y));
-      XSETINT (inev.ie.arg, local_detail);
+      inev.kind = TOUCHSCREEN_BEGIN_EVENT;
+      inev.timestamp = event->touch.time;
+      XSETFRAME (inev.frame_or_window, f);
+      XSETINT (inev.x, lrint (event->touch.x));
+      XSETINT (inev.y, lrint (event->touch.y));
+      XSETINT (inev.arg, local_detail);
       break;
 
     case GDK_TOUCH_UPDATE:
@@ -6691,9 +6712,9 @@ touch_event_cb (GtkWidget *self, GdkEvent *event, gpointer user_data)
       /* Construct the input event.  */
       touchpoint->x = lrint (event->touch.x);
       touchpoint->y = lrint (event->touch.y);
-      inev.ie.kind = TOUCHSCREEN_UPDATE_EVENT;
-      inev.ie.timestamp = event->touch.time;
-      XSETFRAME (inev.ie.frame_or_window, f);
+      inev.kind = TOUCHSCREEN_UPDATE_EVENT;
+      inev.timestamp = event->touch.time;
+      XSETFRAME (inev.frame_or_window, f);
 
       for (touchpoint = dpyinfo->touchpoints;
 	   touchpoint; touchpoint = touchpoint->next)
@@ -6704,7 +6725,7 @@ touch_event_cb (GtkWidget *self, GdkEvent *event, gpointer user_data)
 			 arg);
 	}
 
-      inev.ie.arg = arg;
+      inev.arg = arg;
       break;
 
     case GDK_TOUCH_END:
@@ -6717,14 +6738,14 @@ touch_event_cb (GtkWidget *self, GdkEvent *event, gpointer user_data)
       if (state)
 	{
 	  /* ... generate a suitable event.  */
-	  inev.ie.kind = TOUCHSCREEN_END_EVENT;
-	  inev.ie.timestamp = event->touch.time;
-	  inev.ie.modifiers = (event->type != GDK_TOUCH_END);
-
-	  XSETFRAME (inev.ie.frame_or_window, f);
-	  XSETINT (inev.ie.x, lrint (event->touch.x));
-	  XSETINT (inev.ie.y, lrint (event->touch.y));
-	  XSETINT (inev.ie.arg, local_detail);
+	  inev.kind = TOUCHSCREEN_END_EVENT;
+	  inev.timestamp = event->touch.time;
+	  inev.modifiers = (event->type != GDK_TOUCH_END);
+
+	  XSETFRAME (inev.frame_or_window, f);
+	  XSETINT (inev.x, lrint (event->touch.x));
+	  XSETINT (inev.y, lrint (event->touch.y));
+	  XSETINT (inev.arg, local_detail);
 	}
       break;
 
@@ -6735,9 +6756,9 @@ touch_event_cb (GtkWidget *self, GdkEvent *event, gpointer user_data)
   /* If the above produced a workable event, report the name of the
      device that gave rise to it.  */
 
-  if (inev.ie.kind != NO_EVENT)
+  if (inev.kind != NO_EVENT)
     {
-      inev.ie.device = pgtk_get_device_for_event (dpyinfo, event);
+      inev.device = pgtk_get_device_for_event (dpyinfo, event);
       evq_enqueue (&inev);
 
       /* Next, save this event for future menu activations, unless it is
@@ -6750,7 +6771,7 @@ touch_event_cb (GtkWidget *self, GdkEvent *event, gpointer user_data)
 	}
     }
 
-  return inev.ie.kind != NO_EVENT;
+  return inev.kind != NO_EVENT;
 }
 
 
@@ -6761,12 +6782,12 @@ touch_event_cb (GtkWidget *self, GdkEvent *event, gpointer user_data)
 pgtk_monitors_changed_cb (GdkScreen *screen, gpointer user_data)
 {
   struct terminal *terminal;
-  union buffered_input_event inev;
+  struct input_event inev;
 
-  EVENT_INIT (inev.ie);
+  EVENT_INIT (inev);
   terminal = user_data;
-  inev.ie.kind = MONITORS_CHANGED_EVENT;
-  XSETTERMINAL (inev.ie.arg, terminal);
+  inev.kind = MONITORS_CHANGED_EVENT;
+  XSETTERMINAL (inev.arg, terminal);
 
   evq_enqueue (&inev);
 }
@@ -6928,7 +6949,6 @@ pgtk_selection_event (GtkWidget *widget, GdkEvent *event,
 		      gpointer user_data)
 {
   struct frame *f;
-  union buffered_input_event inev;
 
   if (event->type == GDK_PROPERTY_NOTIFY)
     pgtk_handle_property_notify (&event->property);
@@ -6939,15 +6959,15 @@ pgtk_selection_event (GtkWidget *widget, GdkEvent *event,
 
       if (f)
 	{
-	  EVENT_INIT (inev.ie);
+	  struct selection_input_event sinev = {0};
 
-	  inev.sie.kind = (event->type == GDK_SELECTION_CLEAR
+	  sinev.kind = (event->type == GDK_SELECTION_CLEAR
 			   ? SELECTION_CLEAR_EVENT
 			   : SELECTION_REQUEST_EVENT);
 
-	  SELECTION_EVENT_DPYINFO (&inev.sie) = FRAME_DISPLAY_INFO (f);
-	  SELECTION_EVENT_SELECTION (&inev.sie) = event->selection.selection;
-	  SELECTION_EVENT_TIME (&inev.sie) = event->selection.time;
+	  SELECTION_EVENT_DPYINFO (&sinev) = FRAME_DISPLAY_INFO (f);
+	  SELECTION_EVENT_SELECTION (&sinev) = event->selection.selection;
+	  SELECTION_EVENT_TIME (&sinev) = event->selection.time;
 
 	  if (event->type == GDK_SELECTION_REQUEST)
 	    {
@@ -6957,12 +6977,12 @@ pgtk_selection_event (GtkWidget *widget, GdkEvent *event,
 		 It would make sense to wait for the transfer to
 	         complete.  But I don't know if GDK actually does
 	         that.  */
-	      SELECTION_EVENT_REQUESTOR (&inev.sie) = event->selection.requestor;
-	      SELECTION_EVENT_TARGET (&inev.sie) = event->selection.target;
-	      SELECTION_EVENT_PROPERTY (&inev.sie) = event->selection.property;
+	      SELECTION_EVENT_REQUESTOR (&sinev) = event->selection.requestor;
+	      SELECTION_EVENT_TARGET (&sinev) = event->selection.target;
+	      SELECTION_EVENT_PROPERTY (&sinev) = event->selection.property;
 	    }
 
-	  evq_enqueue (&inev);
+	  evq_selection_enqueue (&sinev);
 	  return TRUE;
 	}
     }
diff --git a/src/xterm.c b/src/xterm.c
index 2ccf267bbd3..aa2116a4b9f 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -18881,7 +18881,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 #endif
 		   int *finish, struct input_event *hold_quit)
 {
-  union buffered_input_event inev;
+  struct input_event inev;
   int count = 0;
   int do_help = 0;
 #ifdef HAVE_XINPUT2
@@ -18924,9 +18924,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
   *finish = X_EVENT_NORMAL;
 
-  EVENT_INIT (inev.ie);
-  inev.ie.kind = NO_EVENT;
-  inev.ie.arg = Qnil;
+  EVENT_INIT (inev);
+  inev.kind = NO_EVENT;
+  inev.arg = Qnil;
 #ifdef HAVE_XINPUT2
   gen_help_device = NULL;
 #endif
@@ -19257,9 +19257,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                 if (!f)
 		  goto OTHER; /* May be a dialog that is to be removed  */
 
-		inev.ie.kind = DELETE_WINDOW_EVENT;
-		inev.ie.timestamp = event->xclient.data.l[1];
-		XSETFRAME (inev.ie.frame_or_window, f);
+		inev.kind = DELETE_WINDOW_EVENT;
+		inev.timestamp = event->xclient.data.l[1];
+		XSETFRAME (inev.frame_or_window, f);
 		goto done;
               }
 
@@ -19413,7 +19413,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 	    /* Convert the scroll bar event to an input event using
 	       the first window entered into the scroll bar event
 	       queue. */
-            x_scroll_bar_to_input_event (dpyinfo, event, &inev.ie);
+	    x_scroll_bar_to_input_event (dpyinfo, event, &inev);
 
 	    *finish = X_EVENT_GOTO_OUT;
             goto done;
@@ -19423,8 +19423,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 	    /* Convert the horizontal scroll bar event to an input
 	       event using the first window entered into the scroll
 	       bar event queue. */
-            x_horizontal_scroll_bar_to_input_event (dpyinfo, event,
-						    &inev.ie);
+	    x_horizontal_scroll_bar_to_input_event (dpyinfo, event, &inev);
 
 	    *finish = X_EVENT_GOTO_OUT;
             goto done;
@@ -19436,7 +19435,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
           {
 	    enum xembed_message msg = event->xclient.data.l[1];
 	    if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT)
-	      x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+	      x_detect_focus_change (dpyinfo, any, event, &inev);
 
 	    *finish = X_EVENT_GOTO_OUT;
             goto done;
@@ -19475,7 +19474,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 	rc = x_coords_from_dnd_message (dpyinfo, (XEvent *) event,
 					&dx, &dy);
 
-	if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie,
+	if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev,
 				  rc, dx, dy))
 	  *finish = X_EVENT_DROP;
       }
@@ -19511,15 +19510,18 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		|| dpyinfo->motif_drag_atom_time <= eventp->time))
 	  dpyinfo->motif_drag_atom = None;
 
-        inev.sie.kind = SELECTION_CLEAR_EVENT;
-        SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
-        SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
-        SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
+	struct selection_input_event sinev = {0};
+	sinev.kind = SELECTION_CLEAR_EVENT;
+	SELECTION_EVENT_DPYINFO (&sinev) = dpyinfo;
+	SELECTION_EVENT_SELECTION (&sinev) = eventp->selection;
+	SELECTION_EVENT_TIME (&sinev) = eventp->time;
 
 	if (x_use_pending_selection_requests)
+	  x_push_selection_request (&sinev);
+	else
 	  {
-	    x_push_selection_request (&inev.sie);
-	    EVENT_INIT (inev.ie);
+	    kbd_buffer_store_selection_event_hold (&sinev, hold_quit);
+	    count++;
 	  }
       }
       break;
@@ -19535,22 +19537,25 @@ handle_one_xevent (struct x_display_info *dpyinfo,
       {
 	const XSelectionRequestEvent *eventp = &event->xselectionrequest;
 
-	inev.sie.kind = SELECTION_REQUEST_EVENT;
-	SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
-	SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
-	SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
-	SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
-	SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
-	SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
+	struct selection_input_event sinev;
+	sinev.kind = SELECTION_REQUEST_EVENT;
+	SELECTION_EVENT_DPYINFO (&sinev) = dpyinfo;
+	SELECTION_EVENT_REQUESTOR (&sinev) = eventp->requestor;
+	SELECTION_EVENT_SELECTION (&sinev) = eventp->selection;
+	SELECTION_EVENT_TARGET (&sinev) = eventp->target;
+	SELECTION_EVENT_PROPERTY (&sinev) = eventp->property;
+	SELECTION_EVENT_TIME (&sinev) = eventp->time;
 
 	/* If drag-and-drop or another modal dialog/menu is in
 	   progress, handle SelectionRequest events immediately, by
 	   pushing it onto the selection queue.  */
 
 	if (x_use_pending_selection_requests)
+	  x_push_selection_request (&sinev);
+	else
 	  {
-	    x_push_selection_request (&inev.sie);
-	    EVENT_INIT (inev.ie);
+	    kbd_buffer_store_selection_event_hold (&sinev, hold_quit);
+	    count++;
 	  }
 
 	if (x_dnd_waiting_for_finish
@@ -19649,7 +19654,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 	      SET_FRAME_ICONIFIED (f, false);
 
 	      f->output_data.x->has_been_visible = true;
-	      inev.ie.kind = DEICONIFY_EVENT;
+	      inev.kind = DEICONIFY_EVENT;
 #if defined USE_GTK && defined HAVE_GTK3
 	      /* If GTK3 wants to impose some old size here (Bug#24526),
 		 tell it that the current size is what we want.  */
@@ -19660,7 +19665,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		  f->was_invisible = false;
 		}
 #endif
-	      XSETFRAME (inev.ie.frame_or_window, f);
+	      XSETFRAME (inev.frame_or_window, f);
 	    }
 	  else if (!not_hidden && !FRAME_ICONIFIED_P (f))
 	    {
@@ -19670,8 +19675,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
 	      SET_FRAME_VISIBLE (f, 0);
 	      SET_FRAME_ICONIFIED (f, true);
-	      inev.ie.kind = ICONIFY_EVENT;
-	      XSETFRAME (inev.ie.frame_or_window, f);
+	      inev.kind = ICONIFY_EVENT;
+	      XSETFRAME (inev.frame_or_window, f);
 	    }
 	}
 
@@ -19686,7 +19691,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 	   set.  Handling UnmapNotify also checks for
 	   _NET_WM_STATE_HIDDEN, and thus suffers from the same
 	   problem.  */
-	x_handle_wm_state (f, &inev.ie);
+	x_handle_wm_state (f, &inev);
 
       if (f && FRAME_X_OUTPUT (f)->alpha_identical_p
 	  && (event->xproperty.atom
@@ -20088,8 +20093,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		  (f, build_string ("UnmapNotify, visible | iconified"));
 
               SET_FRAME_ICONIFIED (f, true);
-	      inev.ie.kind = ICONIFY_EVENT;
-              XSETFRAME (inev.ie.frame_or_window, f);
+	      inev.kind = ICONIFY_EVENT;
+	      XSETFRAME (inev.frame_or_window, f);
             }
 	  else if (CONSP (frame_size_history))
 	    frame_size_history_plain
@@ -20198,8 +20203,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
           if ((not_hidden || FRAME_X_EMBEDDED_P (f)) && iconified)
             {
-              inev.ie.kind = DEICONIFY_EVENT;
-              XSETFRAME (inev.ie.frame_or_window, f);
+	      inev.kind = DEICONIFY_EVENT;
+	      XSETFRAME (inev.frame_or_window, f);
             }
         }
       goto OTHER;
@@ -20465,18 +20470,17 @@ handle_one_xevent (struct x_display_info *dpyinfo,
           orig_keysym = keysym;
 
 	  /* Common for all keysym input events.  */
-	  XSETFRAME (inev.ie.frame_or_window, f);
-	  inev.ie.modifiers
-	    = x_x_to_emacs_modifiers (dpyinfo, modifiers);
-	  inev.ie.timestamp = xkey.time;
+	  XSETFRAME (inev.frame_or_window, f);
+	  inev.modifiers = x_x_to_emacs_modifiers (dpyinfo, modifiers);
+	  inev.timestamp = xkey.time;
 
 	  /* First deal with keysyms which have defined
 	     translations to characters.  */
 	  if (keysym >= 32 && keysym < 128)
 	    /* Avoid explicitly decoding each ASCII character.  */
 	    {
-	      inev.ie.kind = ASCII_KEYSTROKE_EVENT;
-	      inev.ie.code = keysym;
+	      inev.kind = ASCII_KEYSTROKE_EVENT;
+	      inev.code = keysym;
 
 #ifdef HAVE_XINPUT2
 	      if (event->xkey.time == pending_keystroke_time)
@@ -20485,7 +20489,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 					      dpyinfo->pending_keystroke_source);
 
 		  if (source)
-		    inev.ie.device = source->name;
+		    inev.device = source->name;
 		}
 #endif
 
@@ -20496,10 +20500,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 	  if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
 	    {
 	      if (keysym < 0x01000080)
-		inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+		inev.kind = ASCII_KEYSTROKE_EVENT;
 	      else
-		inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
-	      inev.ie.code = keysym & 0xFFFFFF;
+		inev.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+	      inev.code = keysym & 0xFFFFFF;
 
 #ifdef HAVE_XINPUT2
 	      if (event->xkey.time == pending_keystroke_time)
@@ -20508,7 +20512,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 					      dpyinfo->pending_keystroke_source);
 
 		  if (source)
-		    inev.ie.device = source->name;
+		    inev.device = source->name;
 		}
 #endif
 
@@ -20522,10 +20526,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 				Qnil),
 		  FIXNATP (c)))
 	    {
-	      inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
-                              ? ASCII_KEYSTROKE_EVENT
-                              : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-	      inev.ie.code = XFIXNAT (c);
+	      inev.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
+			   ? ASCII_KEYSTROKE_EVENT
+			   : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+	      inev.code = XFIXNAT (c);
 
 #ifdef HAVE_XINPUT2
 	      if (event->xkey.time == pending_keystroke_time)
@@ -20534,7 +20538,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 					      dpyinfo->pending_keystroke_source);
 
 		  if (source)
-		    inev.ie.device = source->name;
+		    inev.device = source->name;
 		}
 #endif
 
@@ -20640,8 +20644,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 	      STORE_KEYSYM_FOR_DEBUG (keysym);
 	      /* make_lispy_event will convert this to a symbolic
 		 key.  */
-	      inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
-	      inev.ie.code = keysym;
+	      inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+	      inev.code = keysym;
 
 #ifdef HAVE_XINPUT2
 	      if (event->xkey.time == pending_keystroke_time)
@@ -20650,7 +20654,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 					      dpyinfo->pending_keystroke_source);
 
 		  if (source)
-		    inev.ie.device = source->name;
+		    inev.device = source->name;
 		}
 #endif
 
@@ -20667,11 +20671,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
 	    if (nbytes)
 	      {
-		inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
-		inev.ie.arg = make_unibyte_string ((char *) copy_bufptr, nbytes);
+		inev.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+		inev.arg = make_unibyte_string ((char *) copy_bufptr, nbytes);
 
 		Fput_text_property (make_fixnum (0), make_fixnum (nbytes),
-				    Qcoding, coding, inev.ie.arg);
+				    Qcoding, coding, inev.arg);
 
 #ifdef HAVE_XINPUT2
 		if (event->xkey.time == pending_keystroke_time
@@ -20685,7 +20689,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 						dpyinfo->pending_keystroke_source);
 
 		    if (source)
-		      inev.ie.device = source->name;
+		      inev.device = source->name;
 		  }
 #endif
 	      }
@@ -20760,7 +20764,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 	 to treat implicit focus correctly.  (bug#65919) */
 #if defined USE_X_TOOLKIT || (defined USE_GTK && !defined HAVE_GTK3)
       if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
-	x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+	x_detect_focus_change (dpyinfo, any, event, &inev);
 #endif /* defined USE_X_TOOLKIT || (defined USE_GTK && !defined HAVE_GTK3) */
 
 #ifdef HAVE_XINPUT2
@@ -20779,7 +20783,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 	 builds.  */
 #if !defined USE_X_TOOLKIT || (!defined USE_GTK || defined HAVE_GTK3)
       if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
-	x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+	x_detect_focus_change (dpyinfo, any, event, &inev);
 #endif /* !defined USE_X_TOOLKIT || (!defined USE_GTK || defined HAVE_GTK3) */
 
       f = any;
@@ -20853,12 +20857,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 	      SET_FRAME_VISIBLE (f, 1);
 	      SET_FRAME_ICONIFIED (f, false);
 	      f->output_data.x->has_been_visible = true;
-	      inev.ie.kind = DEICONIFY_EVENT;
-	      XSETFRAME (inev.ie.frame_or_window, f);
+	      inev.kind = DEICONIFY_EVENT;
+	      XSETFRAME (inev.frame_or_window, f);
 	    }
 	}
 
-      x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+      x_detect_focus_change (dpyinfo, any, event, &inev);
       goto OTHER;
 
     case LeaveNotify:
@@ -20870,7 +20874,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 	 to treat implicit focus correctly.  */
 #if defined USE_X_TOOLKIT || (defined USE_GTK && !defined HAVE_GTK3)
       if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
-	x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+	x_detect_focus_change (dpyinfo, any, event, &inev);
 #endif /* defined USE_X_TOOLKIT || (defined USE_GTK && !defined HAVE_GTK3) */
 
 #ifdef HAVE_XINPUT2
@@ -20902,7 +20906,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 	 builds.  */
 #if !defined USE_X_TOOLKIT || (!defined USE_GTK || defined HAVE_GTK3)
       if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
-	x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+	x_detect_focus_change (dpyinfo, any, event, &inev);
 #endif /* !defined USE_X_TOOLKIT || (!defined USE_GTK || defined HAVE_GTK3) */
 
 #ifdef HAVE_XWIDGETS
@@ -21003,7 +21007,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
       if (dpyinfo->supports_xi2)
 	goto OTHER;
 #endif
-      x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+      x_detect_focus_change (dpyinfo, any, event, &inev);
       goto OTHER;
 
     case MotionNotify:
@@ -21313,8 +21317,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		    && !EQ (window, last_mouse_window)
 		    && !EQ (window, selected_window))
 		  {
-		    inev.ie.kind = SELECT_WINDOW_EVENT;
-		    inev.ie.frame_or_window = window;
+		    inev.kind = SELECT_WINDOW_EVENT;
+		    inev.frame_or_window = window;
 		  }
 
 		/* Remember the last window where we saw the mouse.  */
@@ -21405,13 +21409,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		 hook.  */
 	      if (!x_find_monitors_changed_event (dpyinfo))
 		{
-		  inev.ie.kind = MONITORS_CHANGED_EVENT;
-		  XSETTERMINAL (inev.ie.arg, dpyinfo->terminal);
+		  inev.kind = MONITORS_CHANGED_EVENT;
+		  XSETTERMINAL (inev.arg, dpyinfo->terminal);
 
-		  /* Store this event now since inev.ie.type could be set to
+		  /* Store this event now since inev.type could be set to
 		     MOVE_FRAME_EVENT later.  */
-		  kbd_buffer_store_event (&inev.ie);
-		  inev.ie.kind = NO_EVENT;
+		  kbd_buffer_store_event (&inev);
+		  inev.kind = NO_EVENT;
 		}
 
 	      /* Also update the position of the drag-and-drop
@@ -21678,8 +21682,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 	      if (!FRAME_TOOLTIP_P (f)
 		  && (old_left != f->left_pos || old_top != f->top_pos))
 		{
-		  inev.ie.kind = MOVE_FRAME_EVENT;
-		  XSETFRAME (inev.ie.frame_or_window, f);
+		  inev.kind = MOVE_FRAME_EVENT;
+		  XSETFRAME (inev.frame_or_window, f);
 		}
 	    }
 
@@ -21745,8 +21749,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
             if (!EQ (selected_window, xvw->w) && (event->xbutton.button < 4))
               {
-		inev.ie.kind = SELECT_WINDOW_EVENT;
-		inev.ie.frame_or_window = xvw->w;
+		inev.kind = SELECT_WINDOW_EVENT;
+		inev.frame_or_window = xvw->w;
 	      }
 
 	    *finish = X_EVENT_DROP;
@@ -22002,14 +22006,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 			&& event->xbutton.time > ignore_next_mouse_click_timeout)
 		      {
 			ignore_next_mouse_click_timeout = 0;
-			x_construct_mouse_click (&inev.ie, &event->xbutton,
+			x_construct_mouse_click (&inev, &event->xbutton,
 			                         f, false);
 		      }
 		    if (event->type == ButtonRelease)
 		      ignore_next_mouse_click_timeout = 0;
 		  }
 		else
-		  x_construct_mouse_click (&inev.ie, &event->xbutton, f, false);
+		  x_construct_mouse_click (&inev, &event->xbutton, f, false);
 
 		*finish = X_EVENT_DROP;
 		goto OTHER;
@@ -22079,18 +22083,18 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                           && event->xbutton.time > ignore_next_mouse_click_timeout)
                         {
                           ignore_next_mouse_click_timeout = 0;
-                          x_construct_mouse_click (&inev.ie, &event->xbutton,
+			  x_construct_mouse_click (&inev, &event->xbutton,
                                                    f, false);
                         }
                       if (event->type == ButtonRelease)
                         ignore_next_mouse_click_timeout = 0;
                     }
                   else
-                    x_construct_mouse_click (&inev.ie, &event->xbutton,
+		    x_construct_mouse_click (&inev, &event->xbutton,
                                              f, false);
 
 		  if (!NILP (tab_bar_arg))
-		    inev.ie.arg = tab_bar_arg;
+		    inev.arg = tab_bar_arg;
                 }
 
             if (FRAME_X_EMBEDDED_P (f)
@@ -22109,12 +22113,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                scroll bars.  */
             if (bar && event->xbutton.state & ControlMask)
               {
-                x_scroll_bar_handle_click (bar, event, &inev.ie, Qnil);
+		x_scroll_bar_handle_click (bar, event, &inev, Qnil);
                 *finish = X_EVENT_DROP;
               }
 #else /* not USE_TOOLKIT_SCROLL_BARS */
             if (bar)
-              x_scroll_bar_handle_click (bar, event, &inev.ie, Qnil);
+	      x_scroll_bar_handle_click (bar, event, &inev, Qnil);
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
           }
 
@@ -22171,8 +22175,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		if (!f->output_data.x->saved_menu_event)
 		  f->output_data.x->saved_menu_event = xmalloc (sizeof *event);
 		*f->output_data.x->saved_menu_event = *event;
-		inev.ie.kind = MENU_BAR_ACTIVATE_EVENT;
-		XSETFRAME (inev.ie.frame_or_window, f);
+		inev.kind = MENU_BAR_ACTIVATE_EVENT;
+		XSETFRAME (inev.frame_or_window, f);
 		*finish = X_EVENT_DROP;
 #ifdef USE_MOTIF
 	      }
@@ -22323,8 +22327,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		      SET_FRAME_VISIBLE (f, 1);
 		      SET_FRAME_ICONIFIED (f, false);
 		      f->output_data.x->has_been_visible = true;
-		      inev.ie.kind = DEICONIFY_EVENT;
-		      XSETFRAME (inev.ie.frame_or_window, f);
+		      inev.kind = DEICONIFY_EVENT;
+		      XSETFRAME (inev.frame_or_window, f);
 		    }
 		}
 
@@ -22874,36 +22878,36 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
 		      if (fabs (total_x) > 0 || fabs (total_y) > 0)
 			{
-			  inev.ie.kind = (fabs (total_y) >= fabs (total_x)
-					  ? WHEEL_EVENT : HORIZ_WHEEL_EVENT);
-			  inev.ie.timestamp = xev->time;
-
-			  XSETINT (inev.ie.x, lrint (real_x));
-			  XSETINT (inev.ie.y, lrint (real_y));
-			  XSETFRAME (inev.ie.frame_or_window, f);
-
-			  inev.ie.modifiers = (signbit (fabs (total_y) >= fabs (total_x)
-							? total_y : total_x)
-					       ? down_modifier : up_modifier);
-			  inev.ie.modifiers
+			  inev.kind = (fabs (total_y) >= fabs (total_x)
+				       ? WHEEL_EVENT : HORIZ_WHEEL_EVENT);
+			  inev.timestamp = xev->time;
+
+			  XSETINT (inev.x, lrint (real_x));
+			  XSETINT (inev.y, lrint (real_y));
+			  XSETFRAME (inev.frame_or_window, f);
+
+			  inev.modifiers = (signbit (fabs (total_y) >= fabs (total_x)
+						     ? total_y : total_x)
+					    ? down_modifier : up_modifier);
+			  inev.modifiers
 			    |= x_x_to_emacs_modifiers (dpyinfo,
 						       xev->mods.effective);
-			  inev.ie.arg = list3 (Qnil,
-					       make_float (total_x),
-					       make_float (total_y));
+			  inev.arg = list3 (Qnil,
+					    make_float (total_x),
+					    make_float (total_y));
 			}
 		      else
 			{
-			  inev.ie.kind = TOUCH_END_EVENT;
-			  inev.ie.timestamp = xev->time;
+			  inev.kind = TOUCH_END_EVENT;
+			  inev.timestamp = xev->time;
 
-			  XSETINT (inev.ie.x, lrint (real_x));
-			  XSETINT (inev.ie.y, lrint (real_y));
-			  XSETFRAME (inev.ie.frame_or_window, f);
+			  XSETINT (inev.x, lrint (real_x));
+			  XSETINT (inev.y, lrint (real_y));
+			  XSETFRAME (inev.frame_or_window, f);
 			}
 
 		      if (source && !NILP (source->name))
-			inev.ie.device = source->name;
+			inev.device = source->name;
 
 		      if (!other_valuators_found)
 			goto XI_OTHER;
@@ -23244,11 +23248,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 			  && !EQ (window, last_mouse_window)
 			  && !EQ (window, selected_window))
 			{
-			  inev.ie.kind = SELECT_WINDOW_EVENT;
-			  inev.ie.frame_or_window = window;
+			  inev.kind = SELECT_WINDOW_EVENT;
+			  inev.frame_or_window = window;
 
 			  if (source)
-			    inev.ie.device = source->name;
+			    inev.device = source->name;
 			}
 
 		      /* Remember the last window where we saw the mouse.  */
@@ -23636,11 +23640,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
 		  if (!EQ (selected_window, xvw->w) && (xev->detail < 4))
 		    {
-		      inev.ie.kind = SELECT_WINDOW_EVENT;
-		      inev.ie.frame_or_window = xvw->w;
+		      inev.kind = SELECT_WINDOW_EVENT;
+		      inev.frame_or_window = xvw->w;
 
 		      if (source)
-			inev.ie.device = source->name;
+			inev.device = source->name;
 		    }
 
 		  *finish = X_EVENT_DROP;
@@ -23739,24 +23743,24 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 						     &real_x, &real_y);
 
 			  if (xev->detail <= 5)
-			    inev.ie.kind = WHEEL_EVENT;
+			    inev.kind = WHEEL_EVENT;
 			  else
-			    inev.ie.kind = HORIZ_WHEEL_EVENT;
+			    inev.kind = HORIZ_WHEEL_EVENT;
 
 			  if (source)
-			    inev.ie.device = source->name;
+			    inev.device = source->name;
 
-			  inev.ie.timestamp = xev->time;
+			  inev.timestamp = xev->time;
 
-			  XSETINT (inev.ie.x, real_x);
-			  XSETINT (inev.ie.y, real_y);
-			  XSETFRAME (inev.ie.frame_or_window, f);
+			  XSETINT (inev.x, real_x);
+			  XSETINT (inev.y, real_y);
+			  XSETFRAME (inev.frame_or_window, f);
 
-			  inev.ie.modifiers
+			  inev.modifiers
 			    |= x_x_to_emacs_modifiers (dpyinfo,
 						       xev->mods.effective);
 
-			  inev.ie.modifiers |= xev->detail % 2 ? down_modifier : up_modifier;
+			  inev.modifiers |= xev->detail % 2 ? down_modifier : up_modifier;
 			}
 
 		      *finish = X_EVENT_DROP;
@@ -23777,24 +23781,24 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		      if (xev->evtype == XI_ButtonRelease)
 			{
 			  if (xev->detail <= 5)
-			    inev.ie.kind = WHEEL_EVENT;
+			    inev.kind = WHEEL_EVENT;
 			  else
-			    inev.ie.kind = HORIZ_WHEEL_EVENT;
+			    inev.kind = HORIZ_WHEEL_EVENT;
 
 			  if (source)
-			    inev.ie.device = source->name;
+			    inev.device = source->name;
 
-			  inev.ie.timestamp = xev->time;
+			  inev.timestamp = xev->time;
 
-			  XSETINT (inev.ie.x, lrint (xev->event_x));
-			  XSETINT (inev.ie.y, lrint (xev->event_y));
-			  XSETFRAME (inev.ie.frame_or_window, f);
+			  XSETINT (inev.x, lrint (xev->event_x));
+			  XSETINT (inev.y, lrint (xev->event_y));
+			  XSETFRAME (inev.frame_or_window, f);
 
-			  inev.ie.modifiers
+			  inev.modifiers
 			    |= x_x_to_emacs_modifiers (dpyinfo,
 						       xev->mods.effective);
 
-			  inev.ie.modifiers |= xev->detail % 2 ? down_modifier : up_modifier;
+			  inev.modifiers |= xev->detail % 2 ? down_modifier : up_modifier;
 			}
 
 		      goto XI_OTHER;
@@ -23863,16 +23867,16 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 				&& xev->time > ignore_next_mouse_click_timeout)
 			      {
 				ignore_next_mouse_click_timeout = 0;
-				x_construct_mouse_click (&inev.ie, &bv, f, true);
+				x_construct_mouse_click (&inev, &bv, f, true);
 			      }
 			    if (xev->evtype == XI_ButtonRelease)
 			      ignore_next_mouse_click_timeout = 0;
 			  }
 			else
-			  x_construct_mouse_click (&inev.ie, &bv, f, true);
+			  x_construct_mouse_click (&inev, &bv, f, true);
 
 			if (!NILP (tab_bar_arg))
-			  inev.ie.arg = tab_bar_arg;
+			  inev.arg = tab_bar_arg;
 		      }
 
 		  if (FRAME_X_EMBEDDED_P (f)
@@ -23888,14 +23892,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
 #ifndef USE_TOOLKIT_SCROLL_BARS
 		  if (bar)
-		    x_scroll_bar_handle_click (bar, (XEvent *) &bv, &inev.ie,
+		    x_scroll_bar_handle_click (bar, (XEvent *) &bv, &inev,
 					       source ? source->name : Qnil);
 #else
 		  /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
 		     scroll bars.  */
 		  if (bar && xev->mods.effective & ControlMask)
 		    {
-		      x_scroll_bar_handle_click (bar, (XEvent *) &bv, &inev.ie,
+		      x_scroll_bar_handle_click (bar, (XEvent *) &bv, &inev,
 						 source ? source->name : Qnil);
 		      *finish = X_EVENT_DROP;
 		    }
@@ -23921,8 +23925,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		  device->grab &= ~(1 << xev->detail);
 		}
 
-	      if (source && inev.ie.kind != NO_EVENT)
-		inev.ie.device = source->name;
+	      if (source && inev.kind != NO_EVENT)
+		inev.device = source->name;
 
 	      if (f)
 		f->mouse_moved = false;
@@ -24243,8 +24247,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		  *finish = X_EVENT_DROP;
 #endif /* USE_GTK */
 
-		  XSETFRAME (inev.ie.frame_or_window, f);
-		  inev.ie.timestamp = xev->time;
+		  XSETFRAME (inev.frame_or_window, f);
+		  inev.timestamp = xev->time;
 
 #ifdef HAVE_X_I18N
 		  if (FRAME_XIC (f))
@@ -24356,7 +24360,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 			}
 		    }
 
-		  inev.ie.modifiers = x_x_to_emacs_modifiers (dpyinfo, state);
+		  inev.modifiers = x_x_to_emacs_modifiers (dpyinfo, state);
 
 #ifdef XK_F1
 		  if (x_dnd_in_progress
@@ -24394,11 +24398,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		  if (keysym >= 32 && keysym < 128)
 		    /* Avoid explicitly decoding each ASCII character.  */
 		    {
-		      inev.ie.kind = ASCII_KEYSTROKE_EVENT;
-		      inev.ie.code = keysym;
+		      inev.kind = ASCII_KEYSTROKE_EVENT;
+		      inev.code = keysym;
 
 		      if (source)
-			inev.ie.device = source->name;
+			inev.device = source->name;
 
 		      goto xi_done_keysym;
 		    }
@@ -24407,14 +24411,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		  if (keysym >= 0x01000000 && keysym <= 0x0110FFFF)
 		    {
 		      if (keysym < 0x01000080)
-			inev.ie.kind = ASCII_KEYSTROKE_EVENT;
+			inev.kind = ASCII_KEYSTROKE_EVENT;
 		      else
-			inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+			inev.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
 
 		      if (source)
-			inev.ie.device = source->name;
+			inev.device = source->name;
 
-		      inev.ie.code = keysym & 0xFFFFFF;
+		      inev.code = keysym & 0xFFFFFF;
 		      goto xi_done_keysym;
 		    }
 
@@ -24425,13 +24429,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 					Qnil),
 			  FIXNATP (c)))
 		    {
-		      inev.ie.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
+		      inev.kind = (SINGLE_BYTE_CHAR_P (XFIXNAT (c))
 				      ? ASCII_KEYSTROKE_EVENT
 				      : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-		      inev.ie.code = XFIXNAT (c);
+		      inev.code = XFIXNAT (c);
 
 		      if (source)
-			inev.ie.device = source->name;
+			inev.device = source->name;
 
 		      goto xi_done_keysym;
 		    }
@@ -24535,11 +24539,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		      STORE_KEYSYM_FOR_DEBUG (keysym);
 		      /* make_lispy_event will convert this to a symbolic
 			 key.  */
-		      inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
-		      inev.ie.code = keysym;
+		      inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+		      inev.code = keysym;
 
 		      if (source)
-			inev.ie.device = source->name;
+			inev.device = source->name;
 
 		      goto xi_done_keysym;
 		    }
@@ -24551,14 +24555,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
 		  if (nbytes)
 		    {
-		      inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
-		      inev.ie.arg = make_unibyte_string (copy_bufptr, nbytes);
+		      inev.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+		      inev.arg = make_unibyte_string (copy_bufptr, nbytes);
 
 		      Fput_text_property (make_fixnum (0), make_fixnum (nbytes),
-					  Qcoding, coding, inev.ie.arg);
+					  Qcoding, coding, inev.arg);
 
 		      if (source)
-			inev.ie.device = source->name;
+			inev.device = source->name;
 		    }
 		  goto xi_done_keysym;
 		}
@@ -24912,15 +24916,15 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 						   xev->event_x,
 						   xev->event_y, f);
 
-			  inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT;
-			  inev.ie.timestamp = xev->time;
-			  XSETFRAME (inev.ie.frame_or_window, f);
-			  XSETINT (inev.ie.x, lrint (xev->event_x));
-			  XSETINT (inev.ie.y, lrint (xev->event_y));
-			  XSETINT (inev.ie.arg, local_detail);
+			  inev.kind = TOUCHSCREEN_BEGIN_EVENT;
+			  inev.timestamp = xev->time;
+			  XSETFRAME (inev.frame_or_window, f);
+			  XSETINT (inev.x, lrint (xev->event_x));
+			  XSETINT (inev.y, lrint (xev->event_y));
+			  XSETINT (inev.arg, local_detail);
 
 			  if (source)
-			    inev.ie.device = source->name;
+			    inev.device = source->name;
 			}
 
 		      x_uncatch_errors ();
@@ -25026,9 +25030,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
 	      if (f && device->direct_p)
 		{
-		  inev.ie.kind = TOUCHSCREEN_UPDATE_EVENT;
-		  inev.ie.timestamp = xev->time;
-		  XSETFRAME (inev.ie.frame_or_window, f);
+		  inev.kind = TOUCHSCREEN_UPDATE_EVENT;
+		  inev.timestamp = xev->time;
+		  XSETFRAME (inev.frame_or_window, f);
 
 		  for (touchpoint = device->touchpoints;
 		       touchpoint; touchpoint = touchpoint->next)
@@ -25040,9 +25044,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		    }
 
 		  if (source)
-		    inev.ie.device = source->name;
+		    inev.device = source->name;
 
-		  inev.ie.arg = arg;
+		  inev.arg = arg;
 		}
 
 	      goto XI_OTHER;
@@ -25077,17 +25081,17 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
 		  if (f && device->direct_p)
 		    {
-		      inev.ie.kind = TOUCHSCREEN_END_EVENT;
-		      inev.ie.timestamp = xev->time;
-		      inev.ie.modifiers = state != 2;
+		      inev.kind = TOUCHSCREEN_END_EVENT;
+		      inev.timestamp = xev->time;
+		      inev.modifiers = state != 2;
 
-		      XSETFRAME (inev.ie.frame_or_window, f);
-		      XSETINT (inev.ie.x, lrint (xev->event_x));
-		      XSETINT (inev.ie.y, lrint (xev->event_y));
-		      XSETINT (inev.ie.arg, local_detail);
+		      XSETFRAME (inev.frame_or_window, f);
+		      XSETINT (inev.x, lrint (xev->event_x));
+		      XSETINT (inev.y, lrint (xev->event_y));
+		      XSETINT (inev.arg, local_detail);
 
 		      if (source)
-			inev.ie.device = source->name;
+			inev.device = source->name;
 		    }
 		}
 
@@ -25156,20 +25160,20 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		  if (pev->event == FRAME_X_WINDOW (any))
 		    xi_compute_root_window_offset_pinch (any, pev);
 
-		  inev.ie.kind = PINCH_EVENT;
-		  inev.ie.modifiers
+		  inev.kind = PINCH_EVENT;
+		  inev.modifiers
 		    = x_x_to_emacs_modifiers (dpyinfo, pev->mods.effective);
 
-		  XSETINT (inev.ie.x, lrint (pev->event_x));
-		  XSETINT (inev.ie.y, lrint (pev->event_y));
-		  XSETFRAME (inev.ie.frame_or_window, any);
-		  inev.ie.arg = list4 (make_float (pev->delta_x),
-				       make_float (pev->delta_y),
-				       make_float (pev->scale),
-				       make_float (pev->delta_angle));
+		  XSETINT (inev.x, lrint (pev->event_x));
+		  XSETINT (inev.y, lrint (pev->event_y));
+		  XSETFRAME (inev.frame_or_window, any);
+		  inev.arg = list4 (make_float (pev->delta_x),
+				    make_float (pev->delta_y),
+				    make_float (pev->scale),
+				    make_float (pev->delta_angle));
 
 		  if (source)
-		    inev.ie.device = source->name;
+		    inev.device = source->name;
 		}
 
 	      /* Once again GTK seems to crash when confronted by
@@ -25524,26 +25528,26 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 	       already an undelivered event on the queue.  */
 	    goto OTHER;
 
-	  inev.ie.kind = MONITORS_CHANGED_EVENT;
-	  inev.ie.timestamp = timestamp;
-	  XSETTERMINAL (inev.ie.arg, dpyinfo->terminal);
+	  inev.kind = MONITORS_CHANGED_EVENT;
+	  inev.timestamp = timestamp;
+	  XSETTERMINAL (inev.arg, dpyinfo->terminal);
 
 	  /* Also don't do anything if the monitor configuration
 	     didn't really change.  */
 
 	  current_monitors
-	    = Fx_display_monitor_attributes_list (inev.ie.arg);
+	    = Fx_display_monitor_attributes_list (inev.arg);
 
 	  if (!NILP (Fequal (current_monitors,
 			     dpyinfo->last_monitor_attributes_list)))
-	    inev.ie.kind = NO_EVENT;
+	    inev.kind = NO_EVENT;
 
 	  dpyinfo->last_monitor_attributes_list = current_monitors;
 
 	  if (x_dnd_in_progress && x_dnd_update_tooltip)
 	    x_dnd_monitors = current_monitors;
 
-	  if (inev.ie.kind != NO_EVENT)
+	  if (inev.kind != NO_EVENT)
 	    x_dnd_update_tooltip_now ();
 	}
 #endif
@@ -25591,9 +25595,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
     }
 
  done:
-  if (inev.ie.kind != NO_EVENT)
+  if (inev.kind != NO_EVENT)
     {
-      kbd_buffer_store_buffered_event (&inev, hold_quit);
+      kbd_buffer_store_event_hold (&inev, hold_quit);
       count++;
     }
 
-- 
2.45.2