/* Unprotect the first window to be sent in a
ClientMessage event, since it is now on the stack and
thereby subject to garbage collection. */
- x_unprotect_window_for_callback (dpyinfo);
+ if (event->xclient.serial
+ >= dpyinfo->first_valid_scroll_bar_req)
+ x_unprotect_window_for_callback (dpyinfo);
*finish = X_EVENT_GOTO_OUT;
goto done;
/* Unprotect the first window to be sent in a
ClientMessage event, since it is now on the stack and
thereby subject to garbage collection. */
- x_unprotect_window_for_callback (dpyinfo);
+ if (event->xclient.serial
+ >= dpyinfo->first_valid_scroll_bar_req)
+ x_unprotect_window_for_callback (dpyinfo);
*finish = X_EVENT_GOTO_OUT;
goto done;
#if defined HAVE_XSYNCTRIGGERFENCE && !defined USE_GTK && defined HAVE_CLOCK_GETTIME
x_sync_free_fences (f);
#endif
+
+#ifdef USE_TOOLKIT_SCROLL_BARS
+ /* Since the frame was destroyed, we can no longer guarantee
+ that scroll bar events will be received. Clear
+ protected_windows, and ignore any preceding scroll bar events
+ that happen to still be deliverable. */
+ dpyinfo->n_protected_windows = 0;
+ dpyinfo->first_valid_scroll_bar_req
+ = XNextRequest (dpyinfo->display);
+#endif
}
#ifdef HAVE_GTK3
server_time_monotonic_p will be true). */
int_fast64_t server_time_offset;
#endif
+
+#if defined USE_TOOLKIT_SCROLL_BARS
+ /* Serial number of the first scroll bar event to start listening
+ to. This is necessary because protected_windows is display
+ local, but the destruction of a frame's edit window may cause
+ event windows to vanish before they are delivered, leading to
+ windows remaining protected indefinitely. */
+ unsigned long first_valid_scroll_bar_req;
+#endif
};
#ifdef HAVE_X_I18N