From e1a730017d6f1856b099755f5c47ee7b779a0569 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Fri, 15 Sep 2023 10:30:12 +0800 Subject: [PATCH] Correct bug#65919 * src/process.c (child_signal_notify): Expunge call to non-reentrant function from signal handler. * src/xfns.c (setup_xi_event_mask): Cease selecting for XI_FocusIn and XI_FocusOut under X toolkit builds. * src/xterm.c (xi_handle_interaction, xi_handle_focus_change) (xi_handle_focus_change): Make conditional on GTK 3 or no toolkit builds. (xi_handle_delete_frame, x_free_frame_resources): Adjust correspondingly. (handle_one_xevent) : Examine EnterNotify and LeaveNotify events for focus changes irrespective of whether XI2 is enabled under the X toolkit and GTK 2.x. --- src/process.c | 19 +++++++++++++- src/xfns.c | 10 +++----- src/xterm.c | 68 +++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 82 insertions(+), 15 deletions(-) diff --git a/src/process.c b/src/process.c index dbd677e59d7..7410256dae9 100644 --- a/src/process.c +++ b/src/process.c @@ -7416,7 +7416,24 @@ child_signal_notify (void) eassert (0 <= fd); char dummy = 0; if (emacs_write (fd, &dummy, 1) != 1) - emacs_perror ("writing to child signal FD"); + /* This call is commented out. It calls `emacs_perror', which in + turn invokes a localized version of strerror that is not + reentrant and must not be called within a signal handler: + + __lll_lock_wait_private () at /lib64/libc.so.6 + malloc () at /lib64/libc.so.6 + _nl_make_l10nflist.localalias () at /lib64/libc.so.6 + _nl_find_domain () at /lib64/libc.so.6 + __dcigettext () at /lib64/libc.so.6 + strerror_l () at /lib64/libc.so.6 + emacs_perror (message=message@entry=0x6babc2) + child_signal_notify () at process.c:7419 + handle_child_signal (sig=17) at process.c:7533 + deliver_process_signal (sig=17, handler=0x6186b0>) + () at /lib64/libc.so.6 + _int_malloc () at /lib64/libc.so.6 + in malloc () at /lib64/libc.so.6. */ + /* emacs_perror ("writing to child signal FD") */; #endif } diff --git a/src/xfns.c b/src/xfns.c index aea2f4b880e..0b1e94af9f0 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -4021,6 +4021,7 @@ initial_set_up_x_back_buffer (struct frame *f) } #if defined HAVE_XINPUT2 + static void setup_xi_event_mask (struct frame *f) { @@ -4069,8 +4070,7 @@ setup_xi_event_mask (struct frame *f) XISetMask (m, XI_GesturePinchEnd); } #endif /* HAVE_XINPUT2_4 */ - XISelectEvents (FRAME_X_DISPLAY (f), - FRAME_X_WINDOW (f), + XISelectEvents (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &mask, 1); /* Fortunately `xi_masks' isn't used on GTK 3, where we really have @@ -4085,11 +4085,8 @@ setup_xi_event_mask (struct frame *f) #ifdef USE_X_TOOLKIT XISetMask (m, XI_KeyPress); XISetMask (m, XI_KeyRelease); - XISetMask (m, XI_FocusIn); - XISetMask (m, XI_FocusOut); - XISelectEvents (FRAME_X_DISPLAY (f), - FRAME_OUTER_WINDOW (f), + XISelectEvents (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &mask, 1); memset (m, 0, l); #endif /* USE_X_TOOLKIT */ @@ -4135,6 +4132,7 @@ setup_xi_event_mask (struct frame *f) unblock_input (); } + #endif #ifdef USE_X_TOOLKIT diff --git a/src/xterm.c b/src/xterm.c index 11ccd5ebdb3..9ca7817b8db 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -13170,6 +13170,12 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, #ifdef HAVE_XINPUT2 +/* Disable per-device keyboard focus tracking within X toolkit and GTK + 2.x builds, given that these builds receive updates to the keyboard + input focus as core events. */ + +#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3) + /* Since the input extension assigns a keyboard focus to each master device, there is no longer a 1:1 correspondence between the selected frame and the focus frame immediately after the keyboard @@ -13381,6 +13387,8 @@ xi_focus_handle_for_device (struct x_display_info *dpyinfo, xi_handle_focus_change (dpyinfo); } +#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */ + static void xi_handle_delete_frame (struct x_display_info *dpyinfo, struct frame *f) @@ -13409,6 +13417,7 @@ xi_handle_interaction (struct x_display_info *dpyinfo, struct frame *f, struct xi_device_t *device, Time time) { +#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3) bool change; /* If DEVICE is a pointer, use its attached keyboard device. */ @@ -13435,6 +13444,7 @@ xi_handle_interaction (struct x_display_info *dpyinfo, /* If F isn't currently focused, update the focus state. */ if (change && f != dpyinfo->x_focus_frame) xi_handle_focus_change (dpyinfo); +#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */ } /* Return whether or not XEV actually represents a change in the @@ -20575,6 +20585,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, } #endif + /* Apply the fix for bug#57468 on GTK 3.x and no toolkit builds, + but not GTK+ 2.x and X toolkit builds, where it is required + 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); +#endif /* defined USE_X_TOOLKIT || (defined USE_GTK && !defined HAVE_GTK3) */ + #ifdef HAVE_XINPUT2 /* For whatever reason, the X server continues to deliver EnterNotify and LeaveNotify events despite us selecting for @@ -20585,10 +20603,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (dpyinfo->supports_xi2) goto OTHER; -#endif +#endif /* HAVE_XINPUT2 */ + /* Apply the fix for bug#57468 on GTK 3.x and no toolkit + 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); +#endif /* !defined USE_X_TOOLKIT || (!defined USE_GTK || defined HAVE_GTK3) */ f = any; @@ -20673,6 +20695,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_display_set_last_user_time (dpyinfo, event->xcrossing.time, event->xcrossing.send_event, false); + /* Apply the fix for bug#57468 on GTK 3.x and no toolkit builds, + but not GTK+ 2.x and X toolkit builds, where it is required + 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); +#endif /* defined USE_X_TOOLKIT || (defined USE_GTK && !defined HAVE_GTK3) */ + #ifdef HAVE_XINPUT2 /* For whatever reason, the X server continues to deliver EnterNotify and LeaveNotify events despite us selecting for @@ -20685,7 +20715,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, { #if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3) goto OTHER; -#else +#else /* USE_X_TOOLKIT || (USE_GTK && !HAVE_GTK3) */ /* Unfortunately, X toolkit popups generate LeaveNotify events due to the core grabs they acquire (and our releasing of the device grab). This leads to the mouse @@ -20694,9 +20724,16 @@ handle_one_xevent (struct x_display_info *dpyinfo, outside the frame, in which case no XI_Enter event is generated for the grab. */ goto just_clear_mouse_face; -#endif +#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */ } -#endif +#endif /* HAVE_XINPUT2 */ + + /* Apply the fix for bug#57468 on GTK 3.x and no toolkit + 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); +#endif /* !defined USE_X_TOOLKIT || (!defined USE_GTK || defined HAVE_GTK3) */ #ifdef HAVE_XWIDGETS { @@ -20712,9 +20749,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, } #endif - if (x_top_window_to_frame (dpyinfo, event->xcrossing.window)) - x_detect_focus_change (dpyinfo, any, event, &inev.ie); - #if defined HAVE_XINPUT2 \ && (defined USE_X_TOOLKIT || (defined USE_GTK && !defined HAVE_GTK3)) just_clear_mouse_face: @@ -22082,6 +22116,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, switch (event->xcookie.evtype) { + /* XI focus events aren't employed under X toolkit or GTK+ + 2.x because windows created by these two toolkits are + incompatible with input extension focus events. */ +#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3) case XI_FocusIn: { XIFocusInEvent *focusin; @@ -22134,6 +22172,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, goto XI_OTHER; } +#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */ case XI_Enter: { @@ -22179,8 +22218,11 @@ handle_one_xevent (struct x_display_info *dpyinfo, passive focus from non-top windows at all, since they are an inferiors of the frame's top window, which will get virtual events. */ + +#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3) if (any) xi_focus_handle_for_device (dpyinfo, any, xi_event); +#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */ if (!any) any = x_any_window_to_frame (dpyinfo, enter->event); @@ -22360,8 +22402,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, } #endif +#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3) if (any) xi_focus_handle_for_device (dpyinfo, any, xi_event); +#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */ #ifndef USE_X_TOOLKIT f = x_top_window_to_frame (dpyinfo, leave->event); @@ -24432,9 +24476,11 @@ handle_one_xevent (struct x_display_info *dpyinfo, XIDeviceInfo *info; int i, ndevices, n_disabled, *disabled; struct xi_device_t *device; +#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3) bool any_changed; any_changed = false; +#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */ hev = (XIHierarchyEvent *) xi_event; disabled = SAFE_ALLOCA (sizeof *disabled * hev->num_info); n_disabled = 0; @@ -24451,10 +24497,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, xi_disable_devices (dpyinfo, disabled, n_disabled); n_disabled = 0; +#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3) /* This flag really just means that disabled devices were handled early and should be used in conjunction with n_disabled. */ any_changed = true; +#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */ } /* Under unknown circumstances, multiple @@ -24521,12 +24569,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, event. */ xi_disable_devices (dpyinfo, disabled, n_disabled); +#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3) /* If the device hierarchy has been changed, recompute focus. This might seem like a micro-optimization but it actually keeps the focus from changing in some cases where it would be undesierable. */ if (any_changed || n_disabled) xi_handle_focus_change (dpyinfo); +#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */ goto XI_OTHER; } @@ -29454,6 +29504,7 @@ x_free_frame_resources (struct frame *f) dpyinfo->last_mouse_frame = NULL; #ifdef HAVE_XINPUT2 +#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3) /* Consider a frame being unfocused with no following FocusIn event while an older focus from another seat exists. The client pointer should then revert to the other seat, so handle potential @@ -29461,7 +29512,8 @@ x_free_frame_resources (struct frame *f) if (dpyinfo->supports_xi2) xi_handle_focus_change (dpyinfo); -#endif +#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */ +#endif /* HAVE_XINPUT2 */ unblock_input (); } -- 2.39.5