Regularly poll the X11 event queue.
This change ensures that we deliver events which have been enqueued
in memory in a timely fashion. Previously they would just sit there
and rot until something happened to kick the display connection file
descriptor resulting in greyed out windows and delayed input events.
Added the "--dispatch-one-event-per-loop" switch to experiment with
a mode where the event loop only dispatches one X11 event each
iteration. By default, we dispatch all pending events to minimize
input dispatch latency.
Bug: 661
R=abarth@google.com, jamesr@chromium.org
Review URL: https://codereview.chromium.org/1913913004 .
diff --git a/DEPS b/DEPS
index 4264862..1016b6b 100644
--- a/DEPS
+++ b/DEPS
@@ -21,7 +21,7 @@
'chromium_git': 'https://chromium.googlesource.com',
'skia_revision': 'db284c52e62e8d16708e2065495a3b693b238771',
'v8_revision': '3f036fc0ba4ca4483fe77822f8605c277d37ee24',
- 'base_revision': 'f613c71b2ed7fe4b4eff33fb7fd3b53e640b4359',
+ 'base_revision': '163fb42027bea947916ba4d2fa03aa0ed7c3f99e',
'angle_revision': '46ccef1992a8ede16a596c3dd73cff13c047267d',
'buildtools_revision': '222bd42ce39d1bd8f08fe089b066f49c469e1cdf',
'dart_revision': 'e4db01fdd43f019988a901eb51c72790652760a4',
diff --git a/ui/events/event_switches.cc b/ui/events/event_switches.cc
index dcc0014..a17fd8e 100644
--- a/ui/events/event_switches.cc
+++ b/ui/events/event_switches.cc
@@ -43,4 +43,9 @@
const char kTouchCalibration[] = "touch-calibration";
#endif
+#if defined(USE_X11)
+// Dispatch one event per iteration of the message loop.
+const char kDispatchOneEventPerLoop[] = "dispatch-one-event-per-loop";
+#endif
+
} // namespace switches
diff --git a/ui/events/event_switches.h b/ui/events/event_switches.h
index 94bf37f..ba3ed53 100644
--- a/ui/events/event_switches.h
+++ b/ui/events/event_switches.h
@@ -26,6 +26,10 @@
EVENTS_BASE_EXPORT extern const char kTouchCalibration[];
#endif
+#if defined(USE_X11)
+EVENTS_BASE_EXPORT extern const char kDispatchOneEventPerLoop[];
+#endif
+
} // namespace switches
#endif // UI_EVENTS_EVENTS_SWITCHES_H_
diff --git a/ui/events/platform/x11/x11_event_source.cc b/ui/events/platform/x11/x11_event_source.cc
index 5101f27..84451d1 100644
--- a/ui/events/platform/x11/x11_event_source.cc
+++ b/ui/events/platform/x11/x11_event_source.cc
@@ -9,8 +9,10 @@
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
+#include "base/command_line.h"
#include "base/logging.h"
#include "ui/events/devices/x11/device_data_manager_x11.h"
+#include "ui/events/event_switches.h"
#include "ui/events/event_utils.h"
#include "ui/events/platform/platform_event_dispatcher.h"
#include "ui/events/platform/x11/x11_hotplug_event_handler.h"
@@ -81,6 +83,10 @@
DeviceDataManagerX11::CreateInstance();
InitializeXInput2(display_);
InitializeXkb(display_);
+
+ base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
+ dispatch_one_event_per_loop_ =
+ cmdline->HasSwitch(switches::kDispatchOneEventPerLoop);
}
X11EventSource::~X11EventSource() {
@@ -94,17 +100,19 @@
////////////////////////////////////////////////////////////////////////////////
// X11EventSource, public
-void X11EventSource::DispatchXEvents() {
+bool X11EventSource::DispatchXEvents() {
DCHECK(display_);
- // Handle all pending events.
- // It may be useful to eventually align this event dispatch with vsync, but
- // not yet.
- continue_stream_ = true;
- while (XPending(display_) && continue_stream_) {
+
+ int pending_events = XPending(display_);
+ if (!pending_events)
+ return false;
+ do {
XEvent xevent;
XNextEvent(display_, &xevent);
DispatchEvent(&xevent);
- }
+ } while (--pending_events && continue_stream_ &&
+ !dispatch_one_event_per_loop_);
+ return true;
}
void X11EventSource::BlockUntilWindowMapped(XID window) {
diff --git a/ui/events/platform/x11/x11_event_source.h b/ui/events/platform/x11/x11_event_source.h
index d91fefe..2c3c4e3 100644
--- a/ui/events/platform/x11/x11_event_source.h
+++ b/ui/events/platform/x11/x11_event_source.h
@@ -28,9 +28,10 @@
static X11EventSource* GetInstance();
- // Called by the glib source dispatch function. Processes all (if any)
- // available X events.
- void DispatchXEvents();
+ // Processes pending X events. Returns true if any events were dispatched.
+ // This function should be called repeatedly until it returns false to
+ // ensure all events are processed.
+ bool DispatchXEvents();
// Blocks on the X11 event queue until we receive notification from the
// xserver that |w| has been mapped; StructureNotifyMask events on |w| are
@@ -59,6 +60,9 @@
// available events.
bool continue_stream_;
+ // Dispatch one event at a time.
+ bool dispatch_one_event_per_loop_;
+
scoped_ptr<X11HotplugEventHandler> hotplug_event_handler_;
DISALLOW_COPY_AND_ASSIGN(X11EventSource);
diff --git a/ui/events/platform/x11/x11_event_source_libevent.cc b/ui/events/platform/x11/x11_event_source_libevent.cc
index ff01d2e..c38cba4 100644
--- a/ui/events/platform/x11/x11_event_source_libevent.cc
+++ b/ui/events/platform/x11/x11_event_source_libevent.cc
@@ -14,6 +14,7 @@
namespace {
class X11EventSourceLibevent : public X11EventSource,
+ public base::MessagePumpLibevent::EventSource,
public base::MessagePumpLibevent::Watcher {
public:
explicit X11EventSourceLibevent(XDisplay* display)
@@ -23,6 +24,8 @@
}
~X11EventSourceLibevent() override {
+ if (initialized_)
+ base::MessageLoopForUI::current()->ClearEventSource();
}
private:
@@ -33,15 +36,18 @@
return;
int fd = ConnectionNumber(display());
- base::MessageLoopForUI::current()->WatchFileDescriptor(fd, true,
- base::MessagePumpLibevent::WATCH_READ, &watcher_controller_, this);
+ base::MessageLoopForUI::current()->WatchFileDescriptor(
+ fd, true, base::MessagePumpLibevent::WATCH_READ, &watcher_controller_,
+ this);
+ base::MessageLoopForUI::current()->SetEventSource(this);
initialized_ = true;
}
// PlatformEventSource:
- void OnDispatcherListChanged() override {
- AddEventWatcher();
- }
+ void OnDispatcherListChanged() override { AddEventWatcher(); }
+
+ // base::MessagePumpLibEvent::EventSource:
+ bool Poll() override { return DispatchXEvents(); }
// base::MessagePumpLibevent::Watcher:
void OnFileCanReadWithoutBlocking(int fd) override {