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 |