Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(680)

Unified Diff: ui/events/platform/x11/x11_event_source.cc

Issue 2177823002: X11: Add window cache Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix API Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/events/platform/x11/x11_event_source.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/events/platform/x11/x11_event_source.cc
diff --git a/ui/events/platform/x11/x11_event_source.cc b/ui/events/platform/x11/x11_event_source.cc
index 1a9aa94b6a1954ecaccfb8626ff6dd24c4a9027c..2d9b0c032563c1f81e8faba589c4175ea8394561 100644
--- a/ui/events/platform/x11/x11_event_source.cc
+++ b/ui/events/platform/x11/x11_event_source.cc
@@ -7,6 +7,8 @@
#include <X11/Xatom.h>
#include <X11/XKBlib.h>
#include <X11/Xlib.h>
+#include <X11/Xlib-xcb.h>
+#include <xcb/xcbext.h>
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
@@ -17,6 +19,8 @@
#include "ui/events/platform/platform_event_dispatcher.h"
#include "ui/events/platform/x11/x11_hotplug_event_handler.h"
+#define XLIB_SEQUENCE_COMPARE(a, op, b) (((int64_t)(a) - (int64_t)(b)) op 0)
+
namespace ui {
namespace {
@@ -92,11 +96,22 @@ Bool IsPropertyNotifyForTimestamp(Display* display,
X11EventSource* X11EventSource::instance_ = nullptr;
+X11EventSource::Request::Request(uint32_t sequence)
+ : sequence_(sequence), weak_factory_(this) {}
+X11EventSource::Request::~Request() {}
+
+base::WeakPtr<X11EventSource::Request> X11EventSource::Request::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
X11EventSource::X11EventSource(X11EventSourceDelegate* delegate,
XDisplay* display)
: delegate_(delegate),
display_(display),
+ connection_(XGetXCBConnection(display_)),
dummy_initialized_(false),
+ next_reply_(nullptr),
+ next_error_(nullptr),
continue_stream_(true) {
DCHECK(!instance_);
instance_ = this;
@@ -109,6 +124,7 @@ X11EventSource::X11EventSource(X11EventSourceDelegate* delegate,
X11EventSource::~X11EventSource() {
DCHECK_EQ(this, instance_);
+ DCHECK(!next_reply_ && !next_error_);
instance_ = nullptr;
if (dummy_initialized_)
XDestroyWindow(display_, dummy_window_);
@@ -133,11 +149,22 @@ void X11EventSource::DispatchXEvents() {
// It may be useful to eventually align this event dispatch with vsync, but
// not yet.
continue_stream_ = true;
- while (XPending(display_) && continue_stream_) {
- XEvent xevent;
- XNextEvent(display_, &xevent);
- ExtractCookieDataDispatchEvent(&xevent);
+
+ // Read all available data.
+ XEventsQueued(display_, QueuedAfterReading);
+
+ while (HasNextReply() && HasNextEvent() && continue_stream_) {
+ if (XLIB_SEQUENCE_COMPARE(NextReplySequence(), <=, NextEventSequence()))
+ ProcessNextReply();
+ else
+ ProcessNextEvent();
}
+
+ while (HasNextReply() && continue_stream_)
+ ProcessNextReply();
+
+ while (HasNextEvent() && continue_stream_)
+ ProcessNextEvent();
}
void X11EventSource::DispatchXEventNow(XEvent* event) {
@@ -220,6 +247,44 @@ X11EventSource::GetRootCursorLocationFromCurrentEvent() const {
return base::nullopt;
}
+void X11EventSource::EnqueueRequest(Request* request) {
+ DCHECK(request);
+ request_queue_.emplace_back(request);
+ request->it_ = --request_queue_.end();
+}
+
+void X11EventSource::DiscardRequest(Request* request) {
+ DCHECK(connection_);
+ if ((next_reply_ || next_error_) && request == request_queue_.front().get()) {
+ free(next_reply_);
+ free(next_error_);
+ next_reply_ = nullptr;
+ next_error_ = nullptr;
+ } else {
+ xcb_discard_reply(connection_, request->sequence());
+ }
+ request_queue_.erase(request->it_);
+}
+
+bool X11EventSource::DispatchRequestNow(Request* request) {
+ DCHECK(connection_);
+
+ bool success = false;
+ if ((next_reply_ || next_error_) && request == request_queue_.front().get()) {
+ success = !next_error_;
+ ProcessNextReply();
+ } else {
+ xcb_generic_error_t* error = nullptr;
+ void* reply = xcb_wait_for_reply(connection_, request->sequence(), &error);
+ success = !error;
+ ProcessRequest(request, reinterpret_cast<xcb_generic_reply_t*>(reply),
+ error);
+ free(reply);
+ free(error);
+ }
+ return success;
+}
+
////////////////////////////////////////////////////////////////////////////////
// X11EventSource, protected
@@ -283,6 +348,62 @@ void X11EventSource::BlockOnWindowStructureEvent(XID window, int type) {
} while (event.type != type);
}
+bool X11EventSource::HasNextReply() {
+ if (request_queue_.empty() || xcb_connection_has_error(connection_))
+ return false;
+ if (next_reply_ || next_error_)
+ return true;
+
+ return xcb_poll_for_reply(connection_, request_queue_.front()->sequence(),
+ &next_reply_, &next_error_);
+}
+
+uint32_t X11EventSource::NextReplySequence() {
+ DCHECK(HasNextReply());
+ return request_queue_.front()->sequence();
+}
+
+void X11EventSource::ProcessRequest(Request* request,
+ xcb_generic_reply_t* reply,
+ xcb_generic_error_t* error) {
+ base::WeakPtr<Request> weak_ptr = request->GetWeakPtr();
+ request->OnReply(reply, error);
+ // OnReply() may have chosen to discard this request already.
+ if (weak_ptr)
+ request_queue_.erase(request->it_);
+}
+
+void X11EventSource::ProcessNextReply() {
+ DCHECK(HasNextReply());
+
+ ProcessRequest(request_queue_.front().get(),
+ reinterpret_cast<xcb_generic_reply_t*>(next_reply_),
+ next_error_);
+
+ free(next_reply_);
+ free(next_error_);
+ next_reply_ = nullptr;
+ next_error_ = nullptr;
+}
+
+bool X11EventSource::HasNextEvent() {
+ return XEventsQueued(display_, QueuedAlready);
+}
+
+uint32_t X11EventSource::NextEventSequence() {
+ DCHECK(HasNextEvent());
+ XEvent event;
+ XPeekEvent(display_, &event);
+ return event.xany.serial;
+}
+
+void X11EventSource::ProcessNextEvent() {
+ DCHECK(HasNextEvent());
+ XEvent event;
+ XNextEvent(display_, &event);
+ ExtractCookieDataDispatchEvent(&event);
+}
+
void X11EventSource::StopCurrentEventStream() {
continue_stream_ = false;
}
« no previous file with comments | « ui/events/platform/x11/x11_event_source.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698