Browse Source

Merge pull request #54313 from nekomatata/x11-fix-input-delay-3.x

Rémi Verschelde 3 years ago
parent
commit
2c47e33905
2 changed files with 29 additions and 18 deletions
  1. 28 18
      platform/x11/os_x11.cpp
  2. 1 0
      platform/x11/os_x11.h

+ 28 - 18
platform/x11/os_x11.cpp

@@ -2310,27 +2310,34 @@ void OS_X11::_poll_events() {
 		{
 		{
 			MutexLock mutex_lock(events_mutex);
 			MutexLock mutex_lock(events_mutex);
 
 
-			// Non-blocking wait for next event and remove it from the queue.
-			XEvent ev;
-			while (XCheckIfEvent(x11_display, &ev, _predicate_all_events, nullptr)) {
-				// Check if the input manager wants to process the event.
-				if (XFilterEvent(&ev, None)) {
-					// Event has been filtered by the Input Manager,
-					// it has to be ignored and a new one will be received.
-					continue;
-				}
+			_check_pending_events(polled_events);
+		}
+	}
+}
 
 
-				// Handle selection request events directly in the event thread, because
-				// communication through the x server takes several events sent back and forth
-				// and we don't want to block other programs while processing only one each frame.
-				if (ev.type == SelectionRequest) {
-					_handle_selection_request_event(&(ev.xselectionrequest));
-					continue;
-				}
+void OS_X11::_check_pending_events(LocalVector<XEvent> &r_events) {
+	// Flush to make sure to gather all pending events.
+	XFlush(x11_display);
 
 
-				polled_events.push_back(ev);
-			}
+	// Non-blocking wait for next event and remove it from the queue.
+	XEvent ev;
+	while (XCheckIfEvent(x11_display, &ev, _predicate_all_events, nullptr)) {
+		// Check if the input manager wants to process the event.
+		if (XFilterEvent(&ev, None)) {
+			// Event has been filtered by the Input Manager,
+			// it has to be ignored and a new one will be received.
+			continue;
+		}
+
+		// Handle selection request events directly in the event thread, because
+		// communication through the x server takes several events sent back and forth
+		// and we don't want to block other programs while processing only one each frame.
+		if (ev.type == SelectionRequest) {
+			_handle_selection_request_event(&(ev.xselectionrequest));
+			continue;
 		}
 		}
+
+		r_events.push_back(ev);
 	}
 	}
 }
 }
 
 
@@ -2352,6 +2359,9 @@ void OS_X11::process_xevents() {
 		MutexLock mutex_lock(events_mutex);
 		MutexLock mutex_lock(events_mutex);
 		events = polled_events;
 		events = polled_events;
 		polled_events.clear();
 		polled_events.clear();
+
+		// Check for more pending events to avoid an extra frame delay.
+		_check_pending_events(events);
 	}
 	}
 
 
 	for (uint32_t event_index = 0; event_index < events.size(); ++event_index) {
 	for (uint32_t event_index = 0; event_index < events.size(); ++event_index) {

+ 1 - 0
platform/x11/os_x11.h

@@ -171,6 +171,7 @@ class OS_X11 : public OS_Unix {
 	static void _poll_events_thread(void *ud);
 	static void _poll_events_thread(void *ud);
 	bool _wait_for_events() const;
 	bool _wait_for_events() const;
 	void _poll_events();
 	void _poll_events();
+	void _check_pending_events(LocalVector<XEvent> &r_events);
 
 
 	static Bool _predicate_all_events(Display *display, XEvent *event, XPointer arg);
 	static Bool _predicate_all_events(Display *display, XEvent *event, XPointer arg);
 	static Bool _predicate_clipboard_selection(Display *display, XEvent *event, XPointer arg);
 	static Bool _predicate_clipboard_selection(Display *display, XEvent *event, XPointer arg);