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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « ui/events/platform/x11/x11_event_source.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/events/platform/x11/x11_event_source.h" 5 #include "ui/events/platform/x11/x11_event_source.h"
6 6
7 #include <X11/Xatom.h> 7 #include <X11/Xatom.h>
8 #include <X11/XKBlib.h> 8 #include <X11/XKBlib.h>
9 #include <X11/Xlib.h> 9 #include <X11/Xlib.h>
10 #include <X11/Xlib-xcb.h>
11 #include <xcb/xcbext.h>
10 12
11 #include "base/logging.h" 13 #include "base/logging.h"
12 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
13 #include "ui/base/x/x11_window_event_manager.h" 15 #include "ui/base/x/x11_window_event_manager.h"
14 #include "ui/events/devices/x11/device_data_manager_x11.h" 16 #include "ui/events/devices/x11/device_data_manager_x11.h"
15 #include "ui/events/devices/x11/touch_factory_x11.h" 17 #include "ui/events/devices/x11/touch_factory_x11.h"
16 #include "ui/events/event_utils.h" 18 #include "ui/events/event_utils.h"
17 #include "ui/events/platform/platform_event_dispatcher.h" 19 #include "ui/events/platform/platform_event_dispatcher.h"
18 #include "ui/events/platform/x11/x11_hotplug_event_handler.h" 20 #include "ui/events/platform/x11/x11_hotplug_event_handler.h"
19 21
22 #define XLIB_SEQUENCE_COMPARE(a, op, b) (((int64_t)(a) - (int64_t)(b)) op 0)
23
20 namespace ui { 24 namespace ui {
21 25
22 namespace { 26 namespace {
23 27
24 bool InitializeXkb(XDisplay* display) { 28 bool InitializeXkb(XDisplay* display) {
25 if (!display) 29 if (!display)
26 return false; 30 return false;
27 31
28 int opcode, event, error; 32 int opcode, event, error;
29 int major = XkbMajorVersion; 33 int major = XkbMajorVersion;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 XEvent* event, 89 XEvent* event,
86 XPointer arg) { 90 XPointer arg) {
87 return event->type == PropertyNotify && 91 return event->type == PropertyNotify &&
88 event->xproperty.window == *reinterpret_cast<Window*>(arg); 92 event->xproperty.window == *reinterpret_cast<Window*>(arg);
89 } 93 }
90 94
91 } // namespace 95 } // namespace
92 96
93 X11EventSource* X11EventSource::instance_ = nullptr; 97 X11EventSource* X11EventSource::instance_ = nullptr;
94 98
99 X11EventSource::Request::Request(uint32_t sequence)
100 : sequence_(sequence), weak_factory_(this) {}
101 X11EventSource::Request::~Request() {}
102
103 base::WeakPtr<X11EventSource::Request> X11EventSource::Request::GetWeakPtr() {
104 return weak_factory_.GetWeakPtr();
105 }
106
95 X11EventSource::X11EventSource(X11EventSourceDelegate* delegate, 107 X11EventSource::X11EventSource(X11EventSourceDelegate* delegate,
96 XDisplay* display) 108 XDisplay* display)
97 : delegate_(delegate), 109 : delegate_(delegate),
98 display_(display), 110 display_(display),
111 connection_(XGetXCBConnection(display_)),
99 dummy_initialized_(false), 112 dummy_initialized_(false),
113 next_reply_(nullptr),
114 next_error_(nullptr),
100 continue_stream_(true) { 115 continue_stream_(true) {
101 DCHECK(!instance_); 116 DCHECK(!instance_);
102 instance_ = this; 117 instance_ = this;
103 118
104 DCHECK(delegate_); 119 DCHECK(delegate_);
105 DCHECK(display_); 120 DCHECK(display_);
106 DeviceDataManagerX11::CreateInstance(); 121 DeviceDataManagerX11::CreateInstance();
107 InitializeXkb(display_); 122 InitializeXkb(display_);
108 } 123 }
109 124
110 X11EventSource::~X11EventSource() { 125 X11EventSource::~X11EventSource() {
111 DCHECK_EQ(this, instance_); 126 DCHECK_EQ(this, instance_);
127 DCHECK(!next_reply_ && !next_error_);
112 instance_ = nullptr; 128 instance_ = nullptr;
113 if (dummy_initialized_) 129 if (dummy_initialized_)
114 XDestroyWindow(display_, dummy_window_); 130 XDestroyWindow(display_, dummy_window_);
115 } 131 }
116 132
117 bool X11EventSource::HasInstance() { 133 bool X11EventSource::HasInstance() {
118 return instance_; 134 return instance_;
119 } 135 }
120 136
121 // static 137 // static
122 X11EventSource* X11EventSource::GetInstance() { 138 X11EventSource* X11EventSource::GetInstance() {
123 DCHECK(instance_); 139 DCHECK(instance_);
124 return instance_; 140 return instance_;
125 } 141 }
126 142
127 //////////////////////////////////////////////////////////////////////////////// 143 ////////////////////////////////////////////////////////////////////////////////
128 // X11EventSource, public 144 // X11EventSource, public
129 145
130 void X11EventSource::DispatchXEvents() { 146 void X11EventSource::DispatchXEvents() {
131 DCHECK(display_); 147 DCHECK(display_);
132 // Handle all pending events. 148 // Handle all pending events.
133 // It may be useful to eventually align this event dispatch with vsync, but 149 // It may be useful to eventually align this event dispatch with vsync, but
134 // not yet. 150 // not yet.
135 continue_stream_ = true; 151 continue_stream_ = true;
136 while (XPending(display_) && continue_stream_) { 152
137 XEvent xevent; 153 // Read all available data.
138 XNextEvent(display_, &xevent); 154 XEventsQueued(display_, QueuedAfterReading);
139 ExtractCookieDataDispatchEvent(&xevent); 155
156 while (HasNextReply() && HasNextEvent() && continue_stream_) {
157 if (XLIB_SEQUENCE_COMPARE(NextReplySequence(), <=, NextEventSequence()))
158 ProcessNextReply();
159 else
160 ProcessNextEvent();
140 } 161 }
162
163 while (HasNextReply() && continue_stream_)
164 ProcessNextReply();
165
166 while (HasNextEvent() && continue_stream_)
167 ProcessNextEvent();
141 } 168 }
142 169
143 void X11EventSource::DispatchXEventNow(XEvent* event) { 170 void X11EventSource::DispatchXEventNow(XEvent* event) {
144 ExtractCookieDataDispatchEvent(event); 171 ExtractCookieDataDispatchEvent(event);
145 } 172 }
146 173
147 void X11EventSource::BlockUntilWindowMapped(XID window) { 174 void X11EventSource::BlockUntilWindowMapped(XID window) {
148 BlockOnWindowStructureEvent(window, MapNotify); 175 BlockOnWindowStructureEvent(window, MapNotify);
149 } 176 }
150 177
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 if (!ui::TouchFactory::GetInstance()->ShouldProcessXI2Event(event)) 240 if (!ui::TouchFactory::GetInstance()->ShouldProcessXI2Event(event))
214 break; 241 break;
215 is_valid_event = true; 242 is_valid_event = true;
216 } 243 }
217 244
218 if (is_valid_event) 245 if (is_valid_event)
219 return ui::EventSystemLocationFromNative(event); 246 return ui::EventSystemLocationFromNative(event);
220 return base::nullopt; 247 return base::nullopt;
221 } 248 }
222 249
250 void X11EventSource::EnqueueRequest(Request* request) {
251 DCHECK(request);
252 request_queue_.emplace_back(request);
253 request->it_ = --request_queue_.end();
254 }
255
256 void X11EventSource::DiscardRequest(Request* request) {
257 DCHECK(connection_);
258 if ((next_reply_ || next_error_) && request == request_queue_.front().get()) {
259 free(next_reply_);
260 free(next_error_);
261 next_reply_ = nullptr;
262 next_error_ = nullptr;
263 } else {
264 xcb_discard_reply(connection_, request->sequence());
265 }
266 request_queue_.erase(request->it_);
267 }
268
269 bool X11EventSource::DispatchRequestNow(Request* request) {
270 DCHECK(connection_);
271
272 bool success = false;
273 if ((next_reply_ || next_error_) && request == request_queue_.front().get()) {
274 success = !next_error_;
275 ProcessNextReply();
276 } else {
277 xcb_generic_error_t* error = nullptr;
278 void* reply = xcb_wait_for_reply(connection_, request->sequence(), &error);
279 success = !error;
280 ProcessRequest(request, reinterpret_cast<xcb_generic_reply_t*>(reply),
281 error);
282 free(reply);
283 free(error);
284 }
285 return success;
286 }
287
223 //////////////////////////////////////////////////////////////////////////////// 288 ////////////////////////////////////////////////////////////////////////////////
224 // X11EventSource, protected 289 // X11EventSource, protected
225 290
226 void X11EventSource::ExtractCookieDataDispatchEvent(XEvent* xevent) { 291 void X11EventSource::ExtractCookieDataDispatchEvent(XEvent* xevent) {
227 bool have_cookie = false; 292 bool have_cookie = false;
228 if (xevent->type == GenericEvent && 293 if (xevent->type == GenericEvent &&
229 XGetEventData(xevent->xgeneric.display, &xevent->xcookie)) { 294 XGetEventData(xevent->xgeneric.display, &xevent->xcookie)) {
230 have_cookie = true; 295 have_cookie = true;
231 } 296 }
232 297
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 void X11EventSource::BlockOnWindowStructureEvent(XID window, int type) { 341 void X11EventSource::BlockOnWindowStructureEvent(XID window, int type) {
277 XEvent event; 342 XEvent event;
278 do { 343 do {
279 // Block until there's a StructureNotify event of |type| on |window|. Then 344 // Block until there's a StructureNotify event of |type| on |window|. Then
280 // remove it from the queue and stuff it in |event|. 345 // remove it from the queue and stuff it in |event|.
281 XWindowEvent(display_, window, StructureNotifyMask, &event); 346 XWindowEvent(display_, window, StructureNotifyMask, &event);
282 ExtractCookieDataDispatchEvent(&event); 347 ExtractCookieDataDispatchEvent(&event);
283 } while (event.type != type); 348 } while (event.type != type);
284 } 349 }
285 350
351 bool X11EventSource::HasNextReply() {
352 if (request_queue_.empty() || xcb_connection_has_error(connection_))
353 return false;
354 if (next_reply_ || next_error_)
355 return true;
356
357 return xcb_poll_for_reply(connection_, request_queue_.front()->sequence(),
358 &next_reply_, &next_error_);
359 }
360
361 uint32_t X11EventSource::NextReplySequence() {
362 DCHECK(HasNextReply());
363 return request_queue_.front()->sequence();
364 }
365
366 void X11EventSource::ProcessRequest(Request* request,
367 xcb_generic_reply_t* reply,
368 xcb_generic_error_t* error) {
369 base::WeakPtr<Request> weak_ptr = request->GetWeakPtr();
370 request->OnReply(reply, error);
371 // OnReply() may have chosen to discard this request already.
372 if (weak_ptr)
373 request_queue_.erase(request->it_);
374 }
375
376 void X11EventSource::ProcessNextReply() {
377 DCHECK(HasNextReply());
378
379 ProcessRequest(request_queue_.front().get(),
380 reinterpret_cast<xcb_generic_reply_t*>(next_reply_),
381 next_error_);
382
383 free(next_reply_);
384 free(next_error_);
385 next_reply_ = nullptr;
386 next_error_ = nullptr;
387 }
388
389 bool X11EventSource::HasNextEvent() {
390 return XEventsQueued(display_, QueuedAlready);
391 }
392
393 uint32_t X11EventSource::NextEventSequence() {
394 DCHECK(HasNextEvent());
395 XEvent event;
396 XPeekEvent(display_, &event);
397 return event.xany.serial;
398 }
399
400 void X11EventSource::ProcessNextEvent() {
401 DCHECK(HasNextEvent());
402 XEvent event;
403 XNextEvent(display_, &event);
404 ExtractCookieDataDispatchEvent(&event);
405 }
406
286 void X11EventSource::StopCurrentEventStream() { 407 void X11EventSource::StopCurrentEventStream() {
287 continue_stream_ = false; 408 continue_stream_ = false;
288 } 409 }
289 410
290 void X11EventSource::OnDispatcherListChanged() { 411 void X11EventSource::OnDispatcherListChanged() {
291 if (!hotplug_event_handler_) { 412 if (!hotplug_event_handler_) {
292 hotplug_event_handler_.reset(new X11HotplugEventHandler()); 413 hotplug_event_handler_.reset(new X11HotplugEventHandler());
293 // Force the initial device query to have an update list of active devices. 414 // Force the initial device query to have an update list of active devices.
294 hotplug_event_handler_->OnHotplugEvent(); 415 hotplug_event_handler_->OnHotplugEvent();
295 } 416 }
296 } 417 }
297 418
298 } // namespace ui 419 } // namespace ui
OLDNEW
« 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