1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/gfx/x/connection.h"
6
7 #include <xcb/xcb.h>
8 #include <xcb/xcbext.h>
9
10 #include <algorithm>
11
12 #include "base/auto_reset.h"
13 #include "base/command_line.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/memory/scoped_refptr.h"
16 #include "base/no_destructor.h"
17 #include "base/strings/string16.h"
18 #include "base/threading/thread_local.h"
19 #include "ui/gfx/x/bigreq.h"
20 #include "ui/gfx/x/event.h"
21 #include "ui/gfx/x/keyboard_state.h"
22 #include "ui/gfx/x/randr.h"
23 #include "ui/gfx/x/x11_switches.h"
24 #include "ui/gfx/x/xkb.h"
25 #include "ui/gfx/x/xproto.h"
26 #include "ui/gfx/x/xproto_internal.h"
27 #include "ui/gfx/x/xproto_types.h"
28
29 namespace x11 {
30
31 namespace {
32
33 // On the wire, sequence IDs are 16 bits. In xcb, they're usually extended to
34 // 32 and sometimes 64 bits. In Xlib, they're extended to unsigned long, which
35 // may be 32 or 64 bits depending on the platform. This function is intended to
36 // prevent bugs caused by comparing two differently sized sequences. Also
37 // handles rollover. To use, compare the result of this function with 0. For
38 // example, to compare seq1 <= seq2, use CompareSequenceIds(seq1, seq2) <= 0.
39 template <typename T, typename U>
CompareSequenceIds(T t,U u)40 auto CompareSequenceIds(T t, U u) {
41 static_assert(std::is_unsigned<T>::value, "");
42 static_assert(std::is_unsigned<U>::value, "");
43 // Cast to the smaller of the two types so that comparisons will always work.
44 // If we casted to the larger type, then the smaller type will be zero-padded
45 // and may incorrectly compare less than the other value.
46 using SmallerType =
47 typename std::conditional<sizeof(T) <= sizeof(U), T, U>::type;
48 SmallerType t0 = static_cast<SmallerType>(t);
49 SmallerType u0 = static_cast<SmallerType>(u);
50 using SignedType = typename std::make_signed<SmallerType>::type;
51 return static_cast<SignedType>(t0 - u0);
52 }
53
GetConnectionTLS()54 base::ThreadLocalOwnedPointer<Connection>& GetConnectionTLS() {
55 static base::NoDestructor<base::ThreadLocalOwnedPointer<Connection>> tls;
56 return *tls;
57 }
58
DefaultErrorHandler(const x11::Error * error,const char * request_name)59 void DefaultErrorHandler(const x11::Error* error, const char* request_name) {
60 LOG(WARNING) << "X error received. Request: x11::" << request_name
61 << "Request, Error: " << error->ToString();
62 }
63
DefaultIOErrorHandler()64 void DefaultIOErrorHandler() {
65 LOG(ERROR) << "X connection error received.";
66 }
67
68 class UnknownError : public Error {
69 public:
UnknownError(FutureBase::RawError error_bytes)70 explicit UnknownError(FutureBase::RawError error_bytes)
71 : error_bytes_(error_bytes) {}
72
73 ~UnknownError() override = default;
74
ToString() const75 std::string ToString() const override {
76 std::stringstream ss;
77 ss << "x11::UnknownError{";
78 // Errors are always a fixed 32 bytes.
79 for (size_t i = 0; i < 32; i++) {
80 char buf[3];
81 sprintf(buf, "%02x", error_bytes_->data()[i]);
82 ss << "0x" << buf;
83 if (i != 31)
84 ss << ", ";
85 }
86 ss << "}";
87 return ss.str();
88 }
89
90 private:
91 FutureBase::RawError error_bytes_;
92 };
93
94 } // namespace
95
96 // static
Get()97 Connection* Connection::Get() {
98 auto& tls = GetConnectionTLS();
99 if (Connection* connection = tls.Get())
100 return connection;
101 auto connection = std::make_unique<Connection>();
102 auto* p_connection = connection.get();
103 tls.Set(std::move(connection));
104 return p_connection;
105 }
106
107 // static
Set(std::unique_ptr<x11::Connection> connection)108 void Connection::Set(std::unique_ptr<x11::Connection> connection) {
109 DCHECK_CALLED_ON_VALID_SEQUENCE(connection->sequence_checker_);
110 auto& tls = GetConnectionTLS();
111 DCHECK(!tls.Get());
112 tls.Set(std::move(connection));
113 }
114
Connection(const std::string & address)115 Connection::Connection(const std::string& address)
116 : XProto(this),
117 display_string_(
118 address.empty()
119 ? base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
120 switches::kX11Display)
121 : address),
122 error_handler_(base::BindRepeating(DefaultErrorHandler)),
123 io_error_handler_(base::BindOnce(DefaultIOErrorHandler)) {
124 connection_ =
125 xcb_connect(display_string_.empty() ? nullptr : display_string_.c_str(),
126 &default_screen_id_);
127 DCHECK(connection_);
128 if (Ready()) {
129 auto buf = ReadBuffer(base::MakeRefCounted<UnretainedRefCountedMemory>(
130 xcb_get_setup(XcbConnection())));
131 setup_ = Read<Setup>(&buf);
132 default_screen_ = &setup_.roots[DefaultScreenId()];
133 InitRootDepthAndVisual();
134 } else {
135 // Default-initialize the setup data so we always have something to return.
136 setup_.roots.emplace_back();
137 default_screen_ = &setup_.roots[0];
138 default_screen_->allowed_depths.emplace_back();
139 default_root_depth_ = &default_screen_->allowed_depths[0];
140 default_root_depth_->visuals.emplace_back();
141 default_root_visual_ = &default_root_depth_->visuals[0];
142 }
143
144 ExtensionManager::Init(this);
145 auto enable_bigreq = bigreq().Enable({});
146 // Xlib enables XKB on display creation, so we do that here to maintain
147 // compatibility.
148 xkb()
149 .UseExtension({x11::Xkb::major_version, x11::Xkb::minor_version})
150 .OnResponse(base::BindOnce([](x11::Xkb::UseExtensionResponse response) {
151 if (!response || !response->supported)
152 DVLOG(1) << "Xkb extension not available.";
153 }));
154 Flush();
155 if (auto response = enable_bigreq.Sync())
156 extended_max_request_length_ = response->maximum_request_length;
157
158 const Format* formats[256];
159 memset(formats, 0, sizeof(formats));
160 for (const auto& format : setup_.pixmap_formats)
161 formats[format.depth] = &format;
162
163 for (const auto& depth : default_screen().allowed_depths) {
164 const Format* format = formats[depth.depth];
165 for (const auto& visual : depth.visuals)
166 default_screen_visuals_[visual.visual_id] = VisualInfo{format, &visual};
167 }
168
169 keyboard_state_ = CreateKeyboardState(this);
170
171 InitErrorParsers();
172 }
173
~Connection()174 Connection::~Connection() {
175 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
176
177 platform_event_source.reset();
178 xcb_disconnect(connection_);
179 }
180
XcbConnection()181 xcb_connection_t* Connection::XcbConnection() {
182 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
183 if (io_error_handler_ && xcb_connection_has_error(connection_))
184 std::move(io_error_handler_).Run();
185 return connection_;
186 }
187
GetXlibDisplay(XlibDisplayType type)188 XlibDisplayWrapper Connection::GetXlibDisplay(XlibDisplayType type) {
189 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
190 if (!xlib_display_)
191 xlib_display_ = base::WrapUnique(new XlibDisplay(display_string_));
192 return XlibDisplayWrapper(xlib_display_->display_, type);
193 }
194
Request(unsigned int sequence,FutureBase::ResponseCallback callback)195 Connection::Request::Request(unsigned int sequence,
196 FutureBase::ResponseCallback callback)
197 : sequence(sequence), callback(std::move(callback)) {}
198
Request(Request && other)199 Connection::Request::Request(Request&& other)
200 : sequence(other.sequence),
201 callback(std::move(other.callback)),
202 have_response(other.have_response),
203 reply(std::move(other.reply)),
204 error(std::move(other.error)) {}
205
206 Connection::Request::~Request() = default;
207
HasNextResponse()208 bool Connection::HasNextResponse() {
209 if (requests_.empty())
210 return false;
211 auto& request = requests_.front();
212 if (request.have_response)
213 return true;
214
215 void* reply = nullptr;
216 xcb_generic_error_t* error = nullptr;
217 request.have_response =
218 xcb_poll_for_reply(XcbConnection(), request.sequence, &reply, &error);
219 if (reply)
220 request.reply = base::MakeRefCounted<MallocedRefCountedMemory>(reply);
221 if (error)
222 request.error = base::MakeRefCounted<MallocedRefCountedMemory>(error);
223 return request.have_response;
224 }
225
HasNextEvent()226 bool Connection::HasNextEvent() {
227 while (!events_.empty()) {
228 if (events_.front().Initialized())
229 return true;
230 events_.pop_front();
231 }
232 return false;
233 }
234
GetFd()235 int Connection::GetFd() {
236 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
237 return Ready() ? xcb_get_file_descriptor(XcbConnection()) : -1;
238 }
239
DisplayString() const240 const std::string& Connection::DisplayString() const {
241 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
242 return display_string_;
243 }
244
GetConnectionHostname() const245 std::string Connection::GetConnectionHostname() const {
246 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
247 char* host = nullptr;
248 int display_id = 0;
249 int screen = 0;
250 if (xcb_parse_display(display_string_.c_str(), &host, &display_id, &screen)) {
251 std::string name = host;
252 free(host);
253 return name;
254 }
255 return std::string();
256 }
257
DefaultScreenId() const258 int Connection::DefaultScreenId() const {
259 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
260 // This is not part of the setup data as the server has no concept of a
261 // default screen. Instead, it's part of the display name. Eg in
262 // "localhost:0.0", the screen ID is the second "0".
263 return default_screen_id_;
264 }
265
Ready() const266 bool Connection::Ready() const {
267 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
268 return !xcb_connection_has_error(connection_);
269 }
270
Flush()271 void Connection::Flush() {
272 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
273 xcb_flush(connection_);
274 }
275
Sync()276 void Connection::Sync() {
277 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
278 if (syncing_)
279 return;
280 {
281 base::AutoReset<bool> auto_reset(&syncing_, true);
282 GetInputFocus({}).Sync();
283 }
284 }
285
SynchronizeForTest(bool synchronous)286 void Connection::SynchronizeForTest(bool synchronous) {
287 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
288 synchronous_ = synchronous;
289 if (synchronous_)
290 Sync();
291 }
292
ReadResponses()293 void Connection::ReadResponses() {
294 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
295 while (auto* event = xcb_poll_for_event(XcbConnection())) {
296 events_.emplace_back(base::MakeRefCounted<MallocedRefCountedMemory>(event),
297 this, true);
298 }
299 }
300
WaitForNextEvent()301 Event Connection::WaitForNextEvent() {
302 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
303 if (HasNextEvent()) {
304 Event event = std::move(events_.front());
305 events_.pop_front();
306 return event;
307 }
308 if (auto* xcb_event = xcb_wait_for_event(XcbConnection())) {
309 return Event(base::MakeRefCounted<MallocedRefCountedMemory>(xcb_event),
310 this, true);
311 }
312 return Event();
313 }
314
HasPendingResponses()315 bool Connection::HasPendingResponses() {
316 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
317 return HasNextEvent() || HasNextResponse();
318 }
319
GetVisualInfoFromId(VisualId id) const320 const Connection::VisualInfo* Connection::GetVisualInfoFromId(
321 VisualId id) const {
322 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
323 auto it = default_screen_visuals_.find(id);
324 if (it != default_screen_visuals_.end())
325 return &it->second;
326 return nullptr;
327 }
328
KeysymToKeycode(uint32_t keysym) const329 KeyCode Connection::KeysymToKeycode(uint32_t keysym) const {
330 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
331 return keyboard_state_->KeysymToKeycode(keysym);
332 }
333
KeycodeToKeysym(KeyCode keycode,uint32_t modifiers) const334 uint32_t Connection::KeycodeToKeysym(KeyCode keycode,
335 uint32_t modifiers) const {
336 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
337 return keyboard_state_->KeycodeToKeysym(keycode, modifiers);
338 }
339
Clone() const340 std::unique_ptr<Connection> Connection::Clone() const {
341 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
342 return std::make_unique<Connection>(display_string_);
343 }
344
DetachFromSequence()345 void Connection::DetachFromSequence() {
346 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
347 DETACH_FROM_SEQUENCE(sequence_checker_);
348 }
349
Dispatch(Delegate * delegate)350 void Connection::Dispatch(Delegate* delegate) {
351 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
352
353 auto process_next_response = [&] {
354 DCHECK(!requests_.empty());
355 DCHECK(requests_.front().have_response);
356
357 Request request = std::move(requests_.front());
358 requests_.pop();
359 std::move(request.callback).Run(request.reply, request.error);
360 };
361
362 auto process_next_event = [&] {
363 DCHECK(HasNextEvent());
364
365 Event event = std::move(events_.front());
366 events_.pop_front();
367 PreDispatchEvent(event);
368 delegate->DispatchXEvent(&event);
369 };
370
371 // Handle all pending events.
372 while (delegate->ShouldContinueStream()) {
373 Flush();
374 ReadResponses();
375
376 if (HasNextResponse() && HasNextEvent()) {
377 if (!events_.front().sequence_valid()) {
378 process_next_event();
379 continue;
380 }
381
382 auto next_response_sequence = requests_.front().sequence;
383 auto next_event_sequence = events_.front().sequence();
384
385 // All events have the sequence number of the last processed request
386 // included in them. So if a reply and an event have the same sequence,
387 // the reply must have been received first.
388 if (CompareSequenceIds(next_event_sequence, next_response_sequence) <= 0)
389 process_next_response();
390 else
391 process_next_event();
392 } else if (HasNextResponse()) {
393 process_next_response();
394 } else if (HasNextEvent()) {
395 process_next_event();
396 } else {
397 break;
398 }
399 }
400 }
401
SetErrorHandler(ErrorHandler new_handler)402 Connection::ErrorHandler Connection::SetErrorHandler(ErrorHandler new_handler) {
403 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
404
405 return std::exchange(error_handler_, new_handler);
406 }
407
SetIOErrorHandler(IOErrorHandler new_handler)408 void Connection::SetIOErrorHandler(IOErrorHandler new_handler) {
409 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
410
411 io_error_handler_ = std::move(new_handler);
412 }
413
InitRootDepthAndVisual()414 void Connection::InitRootDepthAndVisual() {
415 for (auto& depth : default_screen_->allowed_depths) {
416 for (auto& visual : depth.visuals) {
417 if (visual.visual_id == default_screen_->root_visual) {
418 default_root_depth_ = &depth;
419 default_root_visual_ = &visual;
420 return;
421 }
422 }
423 }
424 NOTREACHED();
425 }
426
AddRequest(unsigned int sequence,FutureBase::ResponseCallback callback)427 void Connection::AddRequest(unsigned int sequence,
428 FutureBase::ResponseCallback callback) {
429 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
430 DCHECK(requests_.empty() ||
431 CompareSequenceIds(requests_.back().sequence, sequence) < 0);
432
433 requests_.emplace(sequence, std::move(callback));
434 }
435
PreDispatchEvent(const Event & event)436 void Connection::PreDispatchEvent(const Event& event) {
437 if (auto* mapping = event.As<MappingNotifyEvent>()) {
438 if (mapping->request == Mapping::Modifier ||
439 mapping->request == Mapping::Keyboard) {
440 setup_.min_keycode = mapping->first_keycode;
441 setup_.max_keycode = static_cast<x11::KeyCode>(
442 static_cast<int>(mapping->first_keycode) + mapping->count - 1);
443 keyboard_state_->UpdateMapping();
444 }
445 }
446 if (auto* notify = event.As<x11::Xkb::NewKeyboardNotifyEvent>()) {
447 setup_.min_keycode = notify->minKeyCode;
448 setup_.max_keycode = notify->maxKeyCode;
449 keyboard_state_->UpdateMapping();
450 }
451
452 // This is adapted from XRRUpdateConfiguration.
453 if (auto* configure = event.As<ConfigureNotifyEvent>()) {
454 int index = ScreenIndexFromRootWindow(configure->window);
455 if (index != -1) {
456 setup_.roots[index].width_in_pixels = configure->width;
457 setup_.roots[index].height_in_pixels = configure->height;
458 }
459 } else if (auto* screen = event.As<RandR::ScreenChangeNotifyEvent>()) {
460 int index = ScreenIndexFromRootWindow(screen->root);
461 DCHECK_GE(index, 0);
462 bool portrait =
463 static_cast<bool>(screen->rotation & (RandR::Rotation::Rotate_90 |
464 RandR::Rotation::Rotate_270));
465 if (portrait) {
466 setup_.roots[index].width_in_pixels = screen->height;
467 setup_.roots[index].height_in_pixels = screen->width;
468 setup_.roots[index].width_in_millimeters = screen->mheight;
469 setup_.roots[index].height_in_millimeters = screen->mwidth;
470 } else {
471 setup_.roots[index].width_in_pixels = screen->width;
472 setup_.roots[index].height_in_pixels = screen->height;
473 setup_.roots[index].width_in_millimeters = screen->mwidth;
474 setup_.roots[index].height_in_millimeters = screen->mheight;
475 }
476 }
477 }
478
ScreenIndexFromRootWindow(Window root) const479 int Connection::ScreenIndexFromRootWindow(Window root) const {
480 for (size_t i = 0; i < setup_.roots.size(); i++) {
481 if (setup_.roots[i].root == root)
482 return i;
483 }
484 return -1;
485 }
486
ParseError(FutureBase::RawError error_bytes)487 std::unique_ptr<Error> Connection::ParseError(
488 FutureBase::RawError error_bytes) {
489 if (!error_bytes)
490 return nullptr;
491 struct ErrorHeader {
492 uint8_t response_type;
493 uint8_t error_code;
494 uint16_t sequence;
495 };
496 auto error_code = error_bytes->front_as<ErrorHeader>()->error_code;
497 if (auto parser = error_parsers_[error_code])
498 return parser(error_bytes);
499 return std::make_unique<UnknownError>(error_bytes);
500 }
501
GenerateIdImpl()502 uint32_t Connection::GenerateIdImpl() {
503 return xcb_generate_id(connection_);
504 }
505
506 } // namespace x11
507