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

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 test compilation Created 4 years, 3 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
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/events/devices/x11/device_data_manager_x11.h" 15 #include "ui/events/devices/x11/device_data_manager_x11.h"
14 #include "ui/events/devices/x11/touch_factory_x11.h" 16 #include "ui/events/devices/x11/touch_factory_x11.h"
15 #include "ui/events/event_utils.h" 17 #include "ui/events/event_utils.h"
16 #include "ui/events/platform/platform_event_dispatcher.h" 18 #include "ui/events/platform/platform_event_dispatcher.h"
17 #include "ui/events/platform/x11/x11_hotplug_event_handler.h" 19 #include "ui/events/platform/x11/x11_hotplug_event_handler.h"
18 20
21 #define XLIB_SEQUENCE_COMPARE(a, op, b) (((int64_t)(a) - (int64_t)(b)) op 0)
22
19 namespace ui { 23 namespace ui {
20 24
21 namespace { 25 namespace {
22 26
23 bool InitializeXkb(XDisplay* display) { 27 bool InitializeXkb(XDisplay* display) {
24 if (!display) 28 if (!display)
25 return false; 29 return false;
26 30
27 int opcode, event, error; 31 int opcode, event, error;
28 int major = XkbMajorVersion; 32 int major = XkbMajorVersion;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 XEvent* event, 88 XEvent* event,
85 XPointer arg) { 89 XPointer arg) {
86 return event->type == PropertyNotify && 90 return event->type == PropertyNotify &&
87 event->xproperty.window == *reinterpret_cast<Window*>(arg); 91 event->xproperty.window == *reinterpret_cast<Window*>(arg);
88 } 92 }
89 93
90 } // namespace 94 } // namespace
91 95
92 X11EventSource* X11EventSource::instance_ = nullptr; 96 X11EventSource* X11EventSource::instance_ = nullptr;
93 97
98 X11EventSource::Request::Request(uint32_t sequence) : sequence_(sequence) {}
99 X11EventSource::Request::~Request() {}
100
94 X11EventSource::X11EventSource(X11EventSourceDelegate* delegate, 101 X11EventSource::X11EventSource(X11EventSourceDelegate* delegate,
95 XDisplay* display) 102 XDisplay* display)
96 : delegate_(delegate), 103 : delegate_(delegate),
97 display_(display), 104 display_(display),
105 connection_(XGetXCBConnection(display_)),
98 event_timestamp_(CurrentTime), 106 event_timestamp_(CurrentTime),
99 dummy_initialized_(false), 107 dummy_initialized_(false),
108 next_reply_(nullptr),
109 next_error_(nullptr),
100 continue_stream_(true) { 110 continue_stream_(true) {
101 DCHECK(!instance_); 111 DCHECK(!instance_);
102 instance_ = this; 112 instance_ = this;
103 113
104 DCHECK(delegate_); 114 DCHECK(delegate_);
105 DCHECK(display_); 115 DCHECK(display_);
106 DeviceDataManagerX11::CreateInstance(); 116 DeviceDataManagerX11::CreateInstance();
107 InitializeXkb(display_); 117 InitializeXkb(display_);
108 } 118 }
109 119
110 X11EventSource::~X11EventSource() { 120 X11EventSource::~X11EventSource() {
111 DCHECK_EQ(this, instance_); 121 DCHECK_EQ(this, instance_);
122 DCHECK(!next_reply_ && !next_error_);
112 instance_ = nullptr; 123 instance_ = nullptr;
113 if (dummy_initialized_) 124 if (dummy_initialized_)
114 XDestroyWindow(display_, dummy_window_); 125 XDestroyWindow(display_, dummy_window_);
115 } 126 }
116 127
117 bool X11EventSource::HasInstance() { 128 bool X11EventSource::HasInstance() {
118 return instance_; 129 return instance_;
119 } 130 }
120 131
121 // static 132 // static
122 X11EventSource* X11EventSource::GetInstance() { 133 X11EventSource* X11EventSource::GetInstance() {
123 DCHECK(instance_); 134 DCHECK(instance_);
124 return instance_; 135 return instance_;
125 } 136 }
126 137
127 //////////////////////////////////////////////////////////////////////////////// 138 ////////////////////////////////////////////////////////////////////////////////
128 // X11EventSource, public 139 // X11EventSource, public
129 140
130 void X11EventSource::DispatchXEvents() { 141 void X11EventSource::DispatchXEvents() {
131 DCHECK(display_); 142 DCHECK(display_);
132 // Handle all pending events. 143 // Handle all pending events.
133 // It may be useful to eventually align this event dispatch with vsync, but 144 // It may be useful to eventually align this event dispatch with vsync, but
134 // not yet. 145 // not yet.
135 continue_stream_ = true; 146 continue_stream_ = true;
136 while (XPending(display_) && continue_stream_) { 147
137 XEvent xevent; 148 // Read all available data.
138 XNextEvent(display_, &xevent); 149 XEventsQueued(display_, QueuedAfterReading);
139 ExtractCookieDataDispatchEvent(&xevent); 150
151 while (HasNextReply() && HasNextEvent() && continue_stream_) {
152 if (XLIB_SEQUENCE_COMPARE(NextReplySequence(), <=, NextEventSequence()))
153 ProcessNextReply();
154 else
155 ProcessNextEvent();
140 } 156 }
157
158 while (HasNextReply() && continue_stream_)
159 ProcessNextReply();
160
161 while (HasNextEvent() && continue_stream_)
162 ProcessNextEvent();
141 } 163 }
142 164
143 void X11EventSource::DispatchXEventNow(XEvent* event) { 165 void X11EventSource::DispatchXEventNow(XEvent* event) {
144 ExtractCookieDataDispatchEvent(event); 166 ExtractCookieDataDispatchEvent(event);
145 } 167 }
146 168
147 void X11EventSource::BlockUntilWindowMapped(XID window) { 169 void X11EventSource::BlockUntilWindowMapped(XID window) {
148 BlockOnWindowStructureEvent(window, MapNotify); 170 BlockOnWindowStructureEvent(window, MapNotify);
149 } 171 }
150 172
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 } 204 }
183 205
184 Time X11EventSource::GetTimestamp() { 206 Time X11EventSource::GetTimestamp() {
185 if (event_timestamp_ != CurrentTime) { 207 if (event_timestamp_ != CurrentTime) {
186 return event_timestamp_; 208 return event_timestamp_;
187 } 209 }
188 DVLOG(1) << "Making a round trip to get a recent server timestamp."; 210 DVLOG(1) << "Making a round trip to get a recent server timestamp.";
189 return GetCurrentServerTime(); 211 return GetCurrentServerTime();
190 } 212 }
191 213
214 void X11EventSource::EnqueueRequest(Request* request) {
215 DCHECK(request);
216 request_queue_.emplace_back(request);
217 request->it_ = --request_queue_.end();
218 }
219
220 void X11EventSource::DiscardRequest(Request* request) {
221 DCHECK(connection_);
222 xcb_discard_reply(connection_, request->sequence());
223 request_queue_.erase(request->it_);
224 }
225
192 //////////////////////////////////////////////////////////////////////////////// 226 ////////////////////////////////////////////////////////////////////////////////
193 // X11EventSource, protected 227 // X11EventSource, protected
194 228
195 void X11EventSource::ExtractCookieDataDispatchEvent(XEvent* xevent) { 229 void X11EventSource::ExtractCookieDataDispatchEvent(XEvent* xevent) {
196 bool have_cookie = false; 230 bool have_cookie = false;
197 if (xevent->type == GenericEvent && 231 if (xevent->type == GenericEvent &&
198 XGetEventData(xevent->xgeneric.display, &xevent->xcookie)) { 232 XGetEventData(xevent->xgeneric.display, &xevent->xcookie)) {
199 have_cookie = true; 233 have_cookie = true;
200 } 234 }
201 235
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 void X11EventSource::BlockOnWindowStructureEvent(XID window, int type) { 279 void X11EventSource::BlockOnWindowStructureEvent(XID window, int type) {
246 XEvent event; 280 XEvent event;
247 do { 281 do {
248 // Block until there's a StructureNotify event of |type| on |window|. Then 282 // Block until there's a StructureNotify event of |type| on |window|. Then
249 // remove it from the queue and stuff it in |event|. 283 // remove it from the queue and stuff it in |event|.
250 XWindowEvent(display_, window, StructureNotifyMask, &event); 284 XWindowEvent(display_, window, StructureNotifyMask, &event);
251 ExtractCookieDataDispatchEvent(&event); 285 ExtractCookieDataDispatchEvent(&event);
252 } while (event.type != type); 286 } while (event.type != type);
253 } 287 }
254 288
289 bool X11EventSource::HasNextReply() {
290 if (request_queue_.empty() || xcb_connection_has_error(connection_))
291 return false;
292 if (next_reply_ || next_error_)
293 return true;
294
295 return xcb_poll_for_reply(connection_, request_queue_.front()->sequence(),
296 &next_reply_, &next_error_);
297 }
298
299 uint32_t X11EventSource::NextReplySequence() {
300 DCHECK(HasNextReply());
301 return request_queue_.front()->sequence();
302 }
303
304 void X11EventSource::ProcessNextReply() {
305 DCHECK(HasNextReply());
306
307 uint32_t sequence = request_queue_.front()->sequence();
308 request_queue_.front()->OnReply(
309 reinterpret_cast<xcb_generic_reply_t*>(next_reply_), next_error_);
310
311 free(next_reply_);
312 free(next_error_);
313 next_reply_ = nullptr;
314 next_error_ = nullptr;
315
316 // OnReply() may have already discarded this event.
317 if (!request_queue_.empty() && request_queue_.front()->sequence() == sequence)
318 request_queue_.pop_front();
319 }
320
321 bool X11EventSource::HasNextEvent() {
322 return XEventsQueued(display_, QueuedAlready);
323 }
324
325 uint32_t X11EventSource::NextEventSequence() {
326 DCHECK(HasNextEvent());
327 XEvent event;
328 XPeekEvent(display_, &event);
329 return event.xany.serial;
330 }
331
332 void X11EventSource::ProcessNextEvent() {
333 DCHECK(HasNextEvent());
334 XEvent event;
335 XNextEvent(display_, &event);
336 ExtractCookieDataDispatchEvent(&event);
337 }
338
255 void X11EventSource::StopCurrentEventStream() { 339 void X11EventSource::StopCurrentEventStream() {
256 continue_stream_ = false; 340 continue_stream_ = false;
257 } 341 }
258 342
259 void X11EventSource::OnDispatcherListChanged() { 343 void X11EventSource::OnDispatcherListChanged() {
260 if (!hotplug_event_handler_) { 344 if (!hotplug_event_handler_) {
261 hotplug_event_handler_.reset(new X11HotplugEventHandler()); 345 hotplug_event_handler_.reset(new X11HotplugEventHandler());
262 // Force the initial device query to have an update list of active devices. 346 // Force the initial device query to have an update list of active devices.
263 hotplug_event_handler_->OnHotplugEvent(); 347 hotplug_event_handler_->OnHotplugEvent();
264 } 348 }
265 } 349 }
266 350
267 } // namespace ui 351 } // namespace ui
OLDNEW
« ui/base/x/x11_window_cache.cc ('K') | « 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