Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // This file defines utility functions for X11 (Linux only). This code has been | 5 // This file defines utility functions for X11 (Linux only). This code has been |
| 6 // ported from XCB since we can't use XCB on Ubuntu while its 32-bit support | 6 // ported from XCB since we can't use XCB on Ubuntu while its 32-bit support |
| 7 // remains woefully incomplete. | 7 // remains woefully incomplete. |
| 8 | 8 |
| 9 #include "ui/base/x/x11_util.h" | 9 #include "ui/base/x/x11_util.h" |
| 10 | 10 |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 324 } | 324 } |
| 325 | 325 |
| 326 bool IsShapeAvailable() { | 326 bool IsShapeAvailable() { |
| 327 int dummy; | 327 int dummy; |
| 328 static bool is_shape_available = | 328 static bool is_shape_available = |
| 329 XShapeQueryExtension(ui::GetXDisplay(), &dummy, &dummy); | 329 XShapeQueryExtension(ui::GetXDisplay(), &dummy, &dummy); |
| 330 return is_shape_available; | 330 return is_shape_available; |
| 331 | 331 |
| 332 } | 332 } |
| 333 | 333 |
| 334 bool GetEDIDProperty(XID output, unsigned long* nitems, unsigned char* prop) { | |
|
Daniel Erat
2013/01/03 19:04:19
nit: add a comment stating that the caller must fr
Jun Mukai
2013/01/03 21:37:37
Done.
| |
| 335 if (!IsRandRAvailable()) | |
| 336 return false; | |
| 337 | |
| 338 static Atom edid_property = GetAtom(RR_PROPERTY_RANDR_EDID); | |
| 339 | |
| 340 Display* display = GetXDisplay(); | |
| 341 | |
| 342 bool has_edid_property = false; | |
| 343 int num_properties = 0; | |
| 344 Atom* properties = XRRListOutputProperties(display, output, &num_properties); | |
| 345 for (int i = 0; i < num_properties; ++i) { | |
| 346 if (properties[i] == edid_property) { | |
| 347 has_edid_property = true; | |
| 348 break; | |
| 349 } | |
| 350 } | |
| 351 XFree(properties); | |
| 352 if (!has_edid_property) | |
| 353 return false; | |
| 354 | |
| 355 Atom actual_type; | |
| 356 int actual_format; | |
| 357 unsigned long bytes_after; | |
| 358 XRRGetOutputProperty(display, | |
| 359 output, | |
| 360 edid_property, | |
| 361 0, // offset | |
| 362 128, // length | |
| 363 false, // _delete | |
| 364 false, // pending | |
| 365 AnyPropertyType, // req_type | |
| 366 &actual_type, | |
| 367 &actual_format, | |
| 368 nitems, | |
| 369 &bytes_after, | |
| 370 &prop); | |
| 371 DCHECK_EQ(XA_INTEGER, actual_type); | |
| 372 DCHECK_EQ(8, actual_format); | |
| 373 return true; | |
| 374 } | |
| 375 | |
| 334 } // namespace | 376 } // namespace |
| 335 | 377 |
| 336 bool XDisplayExists() { | 378 bool XDisplayExists() { |
| 337 return (GetXDisplay() != NULL); | 379 return (GetXDisplay() != NULL); |
| 338 } | 380 } |
| 339 | 381 |
| 340 Display* GetXDisplay() { | 382 Display* GetXDisplay() { |
| 341 return base::MessagePumpForUI::GetDefaultXDisplay(); | 383 return base::MessagePumpForUI::GetDefaultXDisplay(); |
| 342 } | 384 } |
| 343 | 385 |
| (...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1241 for (int i = 0; i < screen_resources->noutput; ++i) | 1283 for (int i = 0; i < screen_resources->noutput; ++i) |
| 1242 outputs->push_back(screen_resources->outputs[i]); | 1284 outputs->push_back(screen_resources->outputs[i]); |
| 1243 XRRFreeScreenResources(screen_resources); | 1285 XRRFreeScreenResources(screen_resources); |
| 1244 return true; | 1286 return true; |
| 1245 } | 1287 } |
| 1246 | 1288 |
| 1247 bool GetOutputDeviceData(XID output, | 1289 bool GetOutputDeviceData(XID output, |
| 1248 uint16* manufacturer_id, | 1290 uint16* manufacturer_id, |
| 1249 uint32* serial_number, | 1291 uint32* serial_number, |
| 1250 std::string* human_readable_name) { | 1292 std::string* human_readable_name) { |
| 1251 if (!IsRandRAvailable()) | 1293 unsigned long nitems = 0; |
| 1294 unsigned char *prop = NULL; | |
| 1295 if (!GetEDIDProperty(output, &nitems, prop)) | |
|
sadrul
2013/01/03 19:08:32
This doesn't actually set the value of |prop|, doe
Jun Mukai
2013/01/03 21:37:37
aww, right. Fixed.
| |
| 1252 return false; | 1296 return false; |
| 1253 | 1297 |
| 1254 static Atom edid_property = GetAtom(RR_PROPERTY_RANDR_EDID); | |
| 1255 | |
| 1256 Display* display = GetXDisplay(); | |
| 1257 | |
| 1258 bool has_edid_property = false; | |
| 1259 int num_properties = 0; | |
| 1260 Atom* properties = XRRListOutputProperties(display, output, &num_properties); | |
| 1261 for (int i = 0; i < num_properties; ++i) { | |
| 1262 if (properties[i] == edid_property) { | |
| 1263 has_edid_property = true; | |
| 1264 break; | |
| 1265 } | |
| 1266 } | |
| 1267 XFree(properties); | |
| 1268 if (!has_edid_property) | |
| 1269 return false; | |
| 1270 | |
| 1271 Atom actual_type; | |
| 1272 int actual_format; | |
| 1273 unsigned long nitems; | |
| 1274 unsigned long bytes_after; | |
| 1275 unsigned char *prop; | |
| 1276 XRRGetOutputProperty(display, | |
| 1277 output, | |
| 1278 edid_property, | |
| 1279 0, // offset | |
| 1280 128, // length | |
| 1281 false, // _delete | |
| 1282 false, // pending | |
| 1283 AnyPropertyType, // req_type | |
| 1284 &actual_type, | |
| 1285 &actual_format, | |
| 1286 &nitems, | |
| 1287 &bytes_after, | |
| 1288 &prop); | |
| 1289 DCHECK_EQ(XA_INTEGER, actual_type); | |
| 1290 DCHECK_EQ(8, actual_format); | |
| 1291 | |
| 1292 // See http://en.wikipedia.org/wiki/Extended_display_identification_data | 1298 // See http://en.wikipedia.org/wiki/Extended_display_identification_data |
| 1293 // for the details of EDID data format. We use the following data: | 1299 // for the details of EDID data format. We use the following data: |
| 1294 // bytes 8-9: manufacturer EISA ID, in big-endian | 1300 // bytes 8-9: manufacturer EISA ID, in big-endian |
| 1295 // bytes 12-15: represents serial number, in little-endian | 1301 // bytes 12-15: represents serial number, in little-endian |
| 1296 // bytes 54-125: four descriptors (18-bytes each) which may contain | 1302 // bytes 54-125: four descriptors (18-bytes each) which may contain |
| 1297 // the display name. | 1303 // the display name. |
| 1298 const unsigned int kManufacturerOffset = 8; | 1304 const unsigned int kManufacturerOffset = 8; |
| 1299 const unsigned int kManufacturerLength = 2; | 1305 const unsigned int kManufacturerLength = 2; |
| 1300 const unsigned int kSerialNumberOffset = 12; | 1306 const unsigned int kSerialNumberOffset = 12; |
| 1301 const unsigned int kSerialNumberLength = 4; | 1307 const unsigned int kSerialNumberLength = 4; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1365 char c = (*human_readable_name)[i]; | 1371 char c = (*human_readable_name)[i]; |
| 1366 if (!isascii(c) || !isprint(c)) { | 1372 if (!isascii(c) || !isprint(c)) { |
| 1367 human_readable_name->clear(); | 1373 human_readable_name->clear(); |
| 1368 return false; | 1374 return false; |
| 1369 } | 1375 } |
| 1370 } | 1376 } |
| 1371 | 1377 |
| 1372 return true; | 1378 return true; |
| 1373 } | 1379 } |
| 1374 | 1380 |
| 1381 bool GetOutputOverscanFlag(XID output) { | |
|
Daniel Erat
2013/01/03 19:04:19
since this code does a lot of tricky byte-reading,
Jun Mukai
2013/01/03 21:37:37
Added.
| |
| 1382 unsigned long nitems = 0; | |
| 1383 unsigned char *prop = NULL; | |
| 1384 if (!GetEDIDProperty(output, &nitems, prop)) | |
| 1385 return false; | |
| 1386 | |
| 1387 const unsigned int kNumExtensionsOffset = 126; | |
| 1388 if (nitems < kNumExtensionsOffset) { | |
| 1389 XFree(prop); | |
| 1390 return false; | |
| 1391 } | |
| 1392 | |
| 1393 // See http://en.wikipedia.org/wiki/Extended_display_identification_data | |
| 1394 // for the extension format of EDID. Also see | |
| 1395 // http://blogimg.chinaunix.net/blog/upfile2/090903185737.pdf pg.87- | |
| 1396 // for the format of the extensions and how video capability is encoded. | |
| 1397 // - byte 0: tag. should be 02h. | |
| 1398 // - byte 1: revision. only cares revision 3 (03h). | |
| 1399 // - byte 4-: data block. | |
| 1400 const unsigned int kExtensionBase = 128; | |
| 1401 const unsigned int kExtensionSize = 128; | |
| 1402 const unsigned int kDataBlockOffset = 4; | |
| 1403 const unsigned char kCEAExtensionTag = '\x02'; | |
| 1404 const unsigned char kExpectedExtensionRevision = '\x03'; | |
| 1405 const unsigned char kExtendedTag = 7; | |
| 1406 const unsigned char kExtendedVideoCapabilityTag = 0; | |
| 1407 const unsigned int kPTOverscan = 4; | |
| 1408 const unsigned int kITOverscan = 2; | |
| 1409 const unsigned int kCEOverscan = 0; | |
| 1410 | |
| 1411 unsigned char num_extensions = prop[kNumExtensionsOffset]; | |
| 1412 bool result = false; | |
| 1413 bool found = false; | |
| 1414 | |
| 1415 for (size_t i = 0; i < num_extensions && !found; ++i) { | |
| 1416 unsigned char* extension = prop + kExtensionBase + i * kExtensionSize; | |
| 1417 unsigned char tag = extension[0]; | |
| 1418 unsigned char revision = extension[1]; | |
| 1419 if (tag != kCEAExtensionTag || revision != kExpectedExtensionRevision) | |
| 1420 continue; | |
| 1421 | |
| 1422 unsigned char timing_descriptors_start = extension[2]; | |
| 1423 unsigned char* data_block = extension + kDataBlockOffset; | |
| 1424 while (data_block < extension + timing_descriptors_start) { | |
| 1425 // a data block is encoded as: | |
| 1426 // - byte 1 high 3 bits: tag. '07' for extended tags. | |
| 1427 // - byte 1 remaining bits: the length of data block. | |
| 1428 // - byte 2: the extended tag. '0' for video capability. | |
| 1429 // - byte 3: the capability. | |
| 1430 unsigned char tag = data_block[0] >> 5; | |
| 1431 unsigned char payload_length = data_block[0] & 0x1f; | |
| 1432 if (tag != kExtendedTag && payload_length < 2) { | |
| 1433 data_block += payload_length + 1; | |
| 1434 continue; | |
| 1435 } | |
| 1436 | |
| 1437 unsigned char extended_tag_code = data_block[1]; | |
| 1438 // Here doesn't care the difference between preferred video format / | |
|
Daniel Erat
2013/01/03 19:04:19
nit: reword this to something like:
// The differ
Jun Mukai
2013/01/03 21:37:37
Sorry, the comment location was wrong. Moved to th
| |
| 1439 // IT video format / CE video format, since it just checks the | |
| 1440 // possibility. | |
| 1441 if (extended_tag_code != kExtendedVideoCapabilityTag) { | |
| 1442 data_block += payload_length; | |
| 1443 continue; | |
| 1444 } | |
| 1445 | |
| 1446 found = true; | |
| 1447 if ((data_block[2] & (1 << kPTOverscan)) || | |
| 1448 (data_block[2] & (1 << kITOverscan)) || | |
| 1449 (data_block[2] & (1 << kCEOverscan))) { | |
| 1450 result = true; | |
| 1451 } | |
| 1452 break; | |
| 1453 } | |
| 1454 } | |
| 1455 | |
| 1456 XFree(prop); | |
| 1457 return result; | |
| 1458 } | |
| 1459 | |
| 1375 std::vector<std::string> GetDisplayNames(const std::vector<XID>& output_ids) { | 1460 std::vector<std::string> GetDisplayNames(const std::vector<XID>& output_ids) { |
| 1376 std::vector<std::string> names; | 1461 std::vector<std::string> names; |
| 1377 for (size_t i = 0; i < output_ids.size(); ++i) { | 1462 for (size_t i = 0; i < output_ids.size(); ++i) { |
| 1378 std::string display_name; | 1463 std::string display_name; |
| 1379 if (GetOutputDeviceData(output_ids[i], NULL, NULL, &display_name)) | 1464 if (GetOutputDeviceData(output_ids[i], NULL, NULL, &display_name)) |
| 1380 names.push_back(display_name); | 1465 names.push_back(display_name); |
| 1381 } | 1466 } |
| 1382 return names; | 1467 return names; |
| 1383 } | 1468 } |
| 1384 | 1469 |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1721 << "request_code " << static_cast<int>(error_event.request_code) << ", " | 1806 << "request_code " << static_cast<int>(error_event.request_code) << ", " |
| 1722 << "minor_code " << static_cast<int>(error_event.minor_code) | 1807 << "minor_code " << static_cast<int>(error_event.minor_code) |
| 1723 << " (" << request_str << ")"; | 1808 << " (" << request_str << ")"; |
| 1724 } | 1809 } |
| 1725 | 1810 |
| 1726 // ---------------------------------------------------------------------------- | 1811 // ---------------------------------------------------------------------------- |
| 1727 // End of x11_util_internal.h | 1812 // End of x11_util_internal.h |
| 1728 | 1813 |
| 1729 | 1814 |
| 1730 } // namespace ui | 1815 } // namespace ui |
| OLD | NEW |